Mongodb在计算值聚合框架上排序/查询



我有一个与其他集合有关系的集合,我想选择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只做_idscore,所以我在这里做同样的事情。但是您可以根据需要添加其他字段。_id当然总是隐式的,除非另有指定,如"_id" => 0

只剩下"score"值的 $sort 和排序后的总结果的 $limit 。这些都是mapReduce做不到的。

这基本上是基于匹配的属性添加权重,然后"排序"one_answers"限制"结果到最高分数。还要注意,作为一种"数据结构",您想要使用的聚合管道中的变量只是本机代码,而不需要使用mapReduce所做的"字符串化"处理。

相关内容

  • 没有找到相关文章