我想构建一个返回DB中最佳匹配文档的查询。
即我想找到一份包含以下字段的文件 - “动物”:“狗” “颜色”:“棕色” “模式”:“点” “尺寸”: “小”
如果没有包含所有上述fiels及其对应值的文档,我希望查询返回最佳匹配。 f.e {“animal”:“dog”,“color”:“brown”,“size”:“small”}
我可以在mongo db中实现递归查询吗?如果是这样,怎么样? 我应该使用mapReduce,如果是这样,怎么样? 人们可以将这个问题更多地视为一个推荐系统问题,我希望在最适合给定值的项目(文档)上推荐,我很感激,如果有人知道实现上述的好方法
我正在使用mongodb mongoose和nodejs。
谢谢。
答案 0 :(得分:1)
我不确定递归查询的性能影响,但这样的事情应该有效。它从查询中删除最后一个属性,如果未找到匹配项则再次尝试:
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);
});
答案 1 :(得分:0)
鉴于您似乎只搜索文本字段,一种可能性是在MongoDB 2.4中使用新的(当前“实验性的”)text search feature。这允许您在一个或多个字段上创建全文索引,包括field weighting以获取相关性。
例如:
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
}
}
)
Results将按照与相关字段权重相关的评分顺序返回。
请注意,搜索关键字也是stemmed,因此如果您期望完全匹配,这可能会产生一些意想不到的结果。您可以将您的字词放在双引号中,以便利用phrase matching进行更具体的匹配。