Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

Mongodb find best match

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.

Problem courtesy of: Liatz

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);
});
Solution courtesy of: mr.freeze

Discussion

View additional discussion.



This post first appeared on Node.js Recipes, please read the originial post: here

Share the post

Mongodb find best match

×

Subscribe to Node.js Recipes

Get updates delivered right to your inbox!

Thank you for your subscription

×