我有一个与其他集合有关系的集合,我想选择a为用户最相关的记录选择,如下所示:
具有此属性的第一个记录。Some_collection_id == 'someid' &&这一点。Another_collection_id == 'another_id'然后记录有这个。Some_collection_id == 'someid'然后记录有这个。Another_collection_id == 'another_id'然后其他记录
示例:假设主要集合是故事,每个故事都有一个'interest_group'和一个'location'。所有用户都有一个"主要兴趣组"和一个"位置"。我想查询前100个最有趣的故事为一个特定的用户,故事与相同的兴趣组& &;位置权重为5,相同利益集团权重为3,相同位置权重为2,其他权重为1。
我想在查询期间奖励这些积分,这样我就可以根据这些积分对故事集合进行排序,并返回前100个。
所以我可以做4个单独的查询并合并结果客户端(不那么漂亮),或者我可以尝试以正确的顺序收集。
到目前为止,我得出了以下结论:
map = %Q{
function() {
var score = 1;
if (this.some_id == "#{some_id}") {
score = score + 3
}
if (this.another_id == "#{another_id}") {
score = score + 2
}
emit(this._id, { _id: this._id, score: score });
}
}
reduce = %Q{
function(key, values) {
return values;
}
}
MyCollection.map_reduce(map, reduce).out(inline: true)
这将正确返回带有分数的记录的整个集合,但是我不能对分数进行排序,所以我将不得不在客户端进行排序(也很难看,因为我只需要前100个记录左右)
有不同的方法吗?我也检查了聚合框架,但我不知道这将如何解决这个特定的查询。
上面提到的问题并没有真正解释这里的逻辑,但如果我确实抓住了你的一般意思,那么这应该是上面的类似情况,还有你想要的额外增强:
MyCollection.collection.aggregate([
{ "$project" => {
"score" => {
"$add" => [
{ "$cond" => [
{ "$or" => [
{ "$eq" => [ "$some_id" => some_id_var1 ] },
{ "$eq" => [ "$some_id" => some_id_var2 ] },
{ "$eq" => [ "$some_id" => some_id_var3 ] },
{ "$eq" => [ "$some_id" => some_id_var4 ] }
]},
3,
0
]},
{ "$cond" => [
{ "$or" => [
{ "$eq" => [ "$another_id" => another_id_var1 ] },
{ "$eq" => [ "$another_id" => another_id_var2 ] },
{ "$eq" => [ "$another_id" => another_id_var3 ] },
{ "$eq" => [ "$another_id" => another_id_var4 ] }
]},
2,
0
]},
1
]
}
}},
{ "$sort" => { "score" => -1 } },
{ "$limit" => 100 }
])
本质上这是完全相同的事情,因为"some_id"one_answers"another_id"字段正在与一些变量输入进行比较,以查看它们是否匹配并返回一个分数。我在这里所做的补充是你提到"4个查询",所以这听起来像是可变的变化。在这两种情况下,这都应该与 $or
条件相适应。如果您在每种情况下确实只比较一个值,那么只需删除包装$or
。
$cond
操作符本身是"if/then/else"三元操作符。因此,第一个参数是"if",下一个参数分别是true/false
上的返回值。在本例中,您的属性分数或0
。
然后用 add
将所有内容包装起来,使用与您使用的相同的逻辑,生成每个文档的"总分"。
还要注意 $project
要求您在结果中"显式"输出您想要的所有字段。你的mapReduce只做_id
和score
,所以我在这里做同样的事情。但是您可以根据需要添加其他字段。_id
当然总是隐式的,除非另有指定,如"_id" => 0
。
只剩下"score"值的 $sort
和排序后的总结果的 $limit
。这些都是mapReduce做不到的。
这基本上是基于匹配的属性添加权重,然后"排序"one_answers"限制"结果到最高分数。还要注意,作为一种"数据结构",您想要使用的聚合管道中的变量只是本机代码,而不需要使用mapReduce所做的"字符串化"处理。