Mongodb find best match
Problem
I would like to build a Query that returns the best matching document in the DB.
i.e I would like to find a document with the following fields - "animal":"dog" "color":"brown" "pattern":"dots" "size":"small"
If there is no document that has all the above fiels and their corresponding values I would like the query to return the best match. f.e {"animal":"dog", "color":"brown", "size":"small"}
Can I implement a Recursive Query in mongo db? If so, how? Should I use mapReduce, if so, how? One can think of this problem more as a recommendation system problem in the way I would like to recommend on the item(document) that fits best to the given values, I would appreciate if someone knows a good way to implement the above
I'm using mongodb mongoose and nodejs.
Thank you.
Solution
I'm not sure about the performance implications of a recursive query but something like this should work. It removes the last property from the query and tries again if no match is found:
var AnimalSchema = new mongoose.Schema({
atype: { type: String },
color: {type:String},
pattern: {type:String},
size : {type:String}
});
var Animal = mongoose.model('Animal',AnimalSchema);
//test data
//var dalmation = new Animal({
// atype:'dog',
// color: 'black and white',
// pattern: 'spots',
// size: 'big'
//});
//dalmation.save(function(err){
// var yorkie = new Animal({
// atype:'dog',
// color:'brown',
// pattern:'mixed',
// size:'small'
// });
// yorkie.save(function(yer){
// bestMatch({'atype':'dog','size':'big','color':'brown'},function(err,animal){
// console.log(err,animal);
// })
// });
//});
function bestMatch(params,cb){
Animal.findOne(params,function(err,animal){
if (err || !animal){
var keys = Object.keys(params);
if (keys.length){
delete params[keys.pop()];
bestMatch(params,cb);
}else{
cb('No matches',null);
}
}else{
cb(null,animal);
}
});
}
bestMatch({'atype':'dog','size':'big','color':'brown'},function(err,animal){
console.log(err,animal);
});
Discussion
View additional discussion.