Mongodb - 按计算字段

时间:2016-06-28 11:33:26

标签: mongodb

我正在努力寻找mongo db问题的解决方案:

我需要对具有高写入/读取比率的集合运行查询。 该查询包括通过从其他派生的字段对文档进行排序 属于同一文档的字段。 而且,其中一个字段是数组的大小,这使得它更难。

一个简单的例子:

D1 - { _id: 1, field: 1, array_field: [a,b,c,d] } -> score = 1 + 4 = 5
D2 - { _id: 2, field: 2, array_field: [a,b] }     -> score = 2 + 2 = 4

预期结果:

D1 - { _id: 2, score: 4 }
D2 - { _id: 1, score: 5 }

(结果集中不需要得分)

到目前为止我尝试过的解决方案:

  1. 将分数添加为文档的字段,不断更新其他字段的更新。问题:

    • 计算得分后,无法对查询进行参数化(调整)
    • 这是昂贵的,因为分数上的索引必须经常更新
  2. 创建一个汇总管道,使事情变得简单,并解决参数化问题。 但是,性能下降真的很高,因为mongo不能依赖计算字段上的使用索引,导致内存问题(100MB查询错误)。 一种可能的解决方案是启用allowDiskUse标志。但是,查询会变得太慢。

  3. 更新:我想指出查询将每秒运行大约10次。因此,预先计算并将分数存储在不同的文档中可能不是一个可行的解决方案。

    实际使用:因为问题非常困难。让我再给你一些背景信息。我有一个帖子的文件(如facebook帖子)我目前按创建日期和最后更新排序。我希望能够通过" hotness"来对帖子进行排序。这是我所说的得分所定义的。我认为计算得分的一种有趣方式可能如下:

    score = a * likes - b * dislikes + c * num_comments + d * ( now - creation_date)
    

    其中abcd是我可以更改以调整算法的参数。 likesdislikes是引用用户的ObjectID数组,而num_comments只是注释数。 运行查询以提供对REST端点的响应。没有进一步的操作:请求 - >查询 - >响应。

    您是否有衍生/聚合字段的经验? 谢谢!

1 个答案:

答案 0 :(得分:1)

看起来很复杂。

这个查询将完成这项工作,但我会听到你的表现。

db.perlz.aggregate([
// {$match:{whatever is needed here}}
        {
            $project : {
                _id : 1,
                score : {
                    $sum : [{
                            "$size" : "$array_field"
                        }, "$field"]
                }
            }
        }, {
            $sort : {
                score : 1
            }
        }

    ])

由于这是在繁忙的服务器上完成的,我会考虑副本集设置,并尝试通过在从属服务器上发出一些查询来平衡负载。

<强> 修改

根据您的更新,我想知道这些步骤是否适用于此问题:

  1. 更新文档结构,有两种类型:processednewProcessed类似于按工作人员添加到文档分数(影响likes, dislikes, numComments字段)和设置分数 - 然后我们需要计算delta/difference值。

  2. 尝试根据前一点确定最低输入值(预先计算得分)

  3. 将输出限制为已知数量的文档(实现分页)

  4. 根据动态字段值 - 获得分数值不需要大量计算。可以考虑的是项目用于计算和_id的字段,然后使用$lookup作为最后一个阶段,使用带有评分和排序结果的macz父文档。

    欢迎任何评论!