Mongodb-按计算字段排序

a.p*_*riz 5 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
Run Code Online (Sandbox Code Playgroud)

预期结果:

D1 - { _id: 2, score: 4 }
D2 - { _id: 1, score: 5 }
Run Code Online (Sandbox Code Playgroud)

(结果集中不需要分数)

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

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

    • 一旦计算出分数,就无法参数化查询(调整)
    • 这很昂贵,因为分数的索引必须非常频繁地更新
  2. 创建一个聚合管道,使开发变得容易,并解决了参数化问题。但是,性能下降确实很高,因为mongo不能依赖计算字段上的使用索引,从而导致内存问题(100MB查询错误)。一种可能的解决方案是启用该allowDiskUse标志。但是,查询将变得太慢。

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

实用:由于问题非常棘手。让我给您更多背景信息。我有一个帖子文档(例如facebook帖子),目前正在按创建日期和最近更新进行排序。我希望能够按“热门程度”对帖子进行排序,“热门程度”是由我所说的分数定义的。我认为一种有趣的分数计算方法如下:

score = a * likes - b * dislikes + c * num_comments + d * ( now - creation_date)
Run Code Online (Sandbox Code Playgroud)

其中abcd是我的参数可以改变来调整算法。likesdislikesObjectID引用用户的s 数组,而num_comments仅仅是评论数。运行查询以提供对REST端点的响应。没有进一步的操作:请求->查询->响应。

您对派生/汇总字段有任何经验吗?谢谢!

pro*_*r79 2

这看起来是一个复杂的问题。

这个查询可以完成这项工作,但我想听听你关于性能的消息。

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

    ])
Run Code Online (Sandbox Code Playgroud)

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

编辑

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

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

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

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

根据动态字段值 - 获取分值不需要大量计算。可以考虑的是投影计算中使用的字段和 _id,然后用作$lookup最后阶段和带有评分和排序结果的 macz 父文档。

有什么意见欢迎留言!