MongoDB使用自定义函数排序

qfe3c7zg  于 2022-11-03  发布在  Go
关注(0)|答案(1)|浏览(153)

假设我有一个集合,看起来像:

{
  _id: 'aaaaaaaaaaaaaaaaaaaaaaaaa',
  score: 10
  hours: 50
},
{
  _id: 'aaaaaaaaaaaaaaaaaaaaaaaab',
  score: 5
  hours: 55
},
{
  _id: 'aaaaaaaaaaaaaaaaaaaaaaaac',
  score: 15
  hours: 60
}

我想按自定义顺序对此列表进行排序,即

value = (score - 1) / (T + 2) ^ G

score: score
T: current_hours - hours
G: some constant

我假设这将需要编写一个自定义排序函数,该函数除了将current_hours作为输入之外,还将比较score执行该比较并返回排序后的列表。注意,hourscurrent_hours只是从某个任意起点开始经过的小时数。因此,如果I'在应用程序启动80小时后运行此查询时,current_hours的值为80。
创建一个额外的字段value并使其不断更新,对于数百万个文档来说可能过于昂贵。
我知道,如果这是可能的,这看起来会像

db.items.aggregate([
    { "$project" : {
            "_id" :  1,
            "score" : 1,
            "hours" : 1,
            "value" : { SOMETHING HERE, ALSO REQUIRES PASSING current_hours }
        }
    },
    { "$sort" : { "value" : 1 } } 
])

但我不知道value里面有什么

xoshrz7s

xoshrz7s1#

我想value看起来会像这样:

"value": {
        $let: {
          vars: {
            score: "$score",
            t: {
              "$subtract": [
                80,
                "$hours"
              ]
            },
            g: 3
          },
          in: {
            "$divide": [
              {
                "$subtract": [
                  "$$score",
                  1
                ]
              },
              {
                "$pow": [
                  {
                    "$add": [
                      "$$t",
                      2
                    ]
                  },
                  "$$g"
                ]
              }
            ]
          }
        }
      }

Playground example here
虽然它很冗长,但应该是相当简单易懂的。它使用算术表达式运算符来构建您所请求的计算。以下是一些具体的注意事项:

  • 我们在这里使用$let来设置一些vars的用法。这包括current_hours的“运行时”值(根据描述的示例中的80)和3作为G的示例。我们还在这里“重用”score,这不是严格必要的,但这样做是为了下一点的一致性。
  • $引用文档中的字段,而$$引用变量。这就是为什么vars定义中的所有内容都使用$,而in中实际计算的所有内容都使用$$in中对score的引用可以通过字段名来完成($),但我个人更喜欢这种方法的一致性。

相关问题