2015-08-25 116 views
2

我有一个集合,关系到其他收藏品,我想选择的记录了用户最相关的选择如下:有this.some_collection_id ==“someid”mongodb排序/查询计算值聚合框架?

首先记录& & this.another_collection_id = =“another_id” 然后有this.some_collection_id ==“someid” 然后有this.another_collection_id ==“another_id” 那么其他记录

例如记录记载:比方说,主要收集故事,每个故事都有一个'interest_group'和一个位置'。所有用户都有“主要兴趣小组”和“地点”。我想查询一个特定用户的前100个最有趣的故事,同一个兴趣组的故事&位置应该权衡5,同一个利益组只有3, d喜欢在查询过程中授予这些点数,以便我可以根据这些点对故事集合进行排序并返回前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记录左右)

有没有办法做到这一点不同?我也检查了聚合框架,但我没看到这将如何解决这个特定的查询。

+0

那么这个问题有点大,这是没有人触及它的最大原因。你至少可以编辑来显示一些示例文档(只有几个),以及应该与预期结果匹配的内容。这将有助于非常了解。 –

+0

谢谢,让我试着添加一些相关的数据 – ahmeij

+0

请做。我想我有你的要求,但我想确定。 –

回答

2

这里提到的问题并没有真正解释这里的逻辑以及它应该如何,但是如果我确实了解了你的一般含义,那么这应该与上述类似,并且还需要额外的增强功能:

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”和完全一样的东西“another_id”字段进行比较对一些变量输入,看看它们是否匹配,并返回一个分值。我在这里做的补充是你提到“4 queries”,这样听起来像变化的变化。在这两种情况下,这应该仅适用于$or条件。如果您真的只比较每种情况下的一个值,那么只需删除包装$or

$cond运算符本身是“if/then/else”三元操作。所以第一个参数是“if”,下一个参数分别在true/false上返回。在这种情况下,您的归属评分或0

然后用add包装所有文件,为每个文档生成“总分”,使用相同的逻辑。

另请注意,$project要求您输出“显式”结果中的所有字段。你的mapReduce除了_idscore什么都没做,所以我只是在这里做同样的事情。但是您可以根据需要添加其他字段。除非另外指定,否则_id当然总是隐含的,例如"_id" => 0

剩下的就是“分数”值上的$sort,排序后的总结果为$limit。哪些是mapReduce不能做的事情。

这基本上是根据匹配的属性添加权重,然后“排序”和“限制”结果到最高分数。另请注意,作为“数据结构”,您要使用的汇总管道中的变量只是本地代码,并且不需要使用mapReduce进行的“字符串化”处理。

+0

重新阅读我必须说的问题我已经表达了自己在过去更好:)感谢阅读,尽管它和解释如何使用这样的聚合框架。我已经能够获得概念证明查询工作 – ahmeij