MongoDB分区window,获取某个字段值最大的文档

MongoDB partition window, getting the document where a field has the greatest value

我正在将一些东西从 SQL 翻译成 MongoDB。

我有一个 Mongo table 设置,其中文档可以包含大量信息。有两个id,id_1id_2id_2 的默认值为 -1id_1id_2之间存在1->n的关系。例如,数据可能如下所示:

id_1   id_2   info
---- | ---- | ----
120   -1      'dont'
120   444     'show'
123   -1      'test'
124   -1      'hello'
125   -1      'world'
125   123     'oh wait'
126   -1      'help'
126   201     'me'
127   -1      'sql'
127   206     'hell'

我想要一个 Mongo 数据库查询,它获得与 id_1 关联的最高 id_2

给定 id_1 包含 (123,124,125,126,127)id_2 包含 (-1,-1,123,201,206):

的答案应该是这样的
id_1   id_2   info
---- | ---- | ----
123    -1     'test'
124    -1     'hello'
125    123    'oh wait'
126    201    'me'
127    206    'hell' 

在 SQL 中,可以使用以下方法完成此操作:

WITH cte AS (
    SELECT *, ROW_NUMBER() OVER (PARTITION BY id_1 ORDER BY id_2 DESC) rn
    FROM ids
    WHERE id_1 IN (123, 124, 125, 126, 127) AND
          id_2 IN (-1, -1, 123, 201, 206)
)

SELECT id_1, id_2, info
FROM cte
WHERE rn = 1;

在 Mongo 中,这可以通过 $group 子句来完成,但是,它 非常 慢。见下文:

{
      '$sort' : {
           'id_1': 1,
           'id_2': 1   
      }  
},
{
      '$group' : {
          '_id': '$id_1',
          'id_1': {'$first': '$id_1'},
          'info': { '$last': '$info'}
      }  
}

我在文档中找到了这个:

https://docs.mongodb.com/manual/reference/operator/aggregation/setWindowFields/#std-label-setWindowFields-window

但是,我没有得到好的结果。我想我误会了window。这是我拥有的:

    {
            '$match' : {
                'id_1': {'$in' : [123,124,125,126,127]},
                'id_2': {'$in' : [-1,-1,123,201,206]}
            }
    },
    {
        '$setWindowFields': {
            'partitionBy': 'id_1',
            'sortBy' : {
                'id_2': -1
            },
            'output': {
                'info': {
                    '$last': '$info'    
                },
            }
        }
    },
    {
        '$project' : {
            'id_1' : 1,
            'id_2' : 1,
            'info' : 1
        }
    }

除了输出 id_1id_2 的每个组合的每个信息之外,这似乎并没有真正做任何事情。同样,将 [0,1] 的范围添加到 output 中的 window 只会导致错误:

Missing _sortExpr with range-based bounds

有谁知道如何获得与我在 SQL 中相同的结果?

  • $match 匹配 id_1id_2
  • $setWindowFields unbounded 按分区检查整个组
  • $match 只保留 id_2 = max,表示它是最大的文档。
  • $unset 删除最大值,因为它是不必要的
db.collection.aggregate([
  {
    "$match": {
      "id_1": { "$in": [ 123, 124, 125, 126, 127 ] },
      "id_2": { "$in": [ -1, 123, 201, 206 ] }
    }
  },
  {
    $setWindowFields: {
      partitionBy: "$id_1",
      sortBy: { id_2: 1 },
      output: {
        max: {
          $max: "$id_2",
          window: {
            documents: [ "unbounded", "unbounded" ]
          }
        }
      }
    }
  },
  {
    "$match": {
      $expr: { "$eq": [ "$id_2", "$max" ] }
    }
  },
  {
    "$unset": "max"
  }
])

mongoplayground