3

我想构建一个返回数据库中最佳匹配文档的查询。

即我想找到一个包含以下字段的文档-“动物”:“狗”“颜色”:“棕色”“图案”:“点”“大小”:“小”

如果没有包含上述所有字段及其对应值的文档,我希望查询返回最佳匹配。fe {“动物”:“狗”,“颜色”:“棕色”,“尺寸”:“小”}

我可以在 mongo db 中实现递归查询吗?如果是这样,怎么做?我应该使用 mapReduce,如果是,如何使用?人们可以将此问题更多地视为推荐系统问题,我想推荐最适合给定值的项目(文档),如果有人知道实现上述方法的好方法,我将不胜感激

我正在使用 mongodb mongoose 和 nodejs。

谢谢你。

4

2 回答 2

2

我不确定递归查询的性能影响,但这样的事情应该可以工作。它从查询中删除最后一个属性,如果没有找到匹配项,则再次尝试:

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);
});
于 2013-04-07T15:19:16.687 回答
1

鉴于您似乎只搜索文本字段,一种可能性是使用 MongoDB 2.4 中新的(目前是“实验性的”)文本搜索功能。这允许您在一个或多个字段上创建全文索引,包括相关性的字段加权

例如:

db.collection.ensureIndex(
    // Fields to index
    {
        animal:  "text",
        color:   "text",
        pattern: "text",
        size:    "text"
    },

    // Options
    {
        name: "best_match_index",

        // Adjust field weights (default is 1)
        weights: {
            animal: 5,  // Most relevant search field
            size:   4   // Also relevant
       }
    }
)

结果将根据相关字段权重按与评分相关的顺序返回。

请注意,搜索关键字也是stemmed,因此如果您期望完全匹配,这可能会产生一些意想不到的结果。您可以将您的术语放在双引号中,以利用短语匹配进行更具体的匹配。

于 2013-04-08T08:35:35.870 回答