MongoDB分区window,获取某个字段值最大的文档
MongoDB partition window, getting the document where a field has the greatest value
我正在将一些东西从 SQL 翻译成 MongoDB。
我有一个 Mongo table 设置,其中文档可以包含大量信息。有两个id,id_1
和id_2
。 id_2
的默认值为 -1
。 id_1
和id_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'}
}
}
我在文档中找到了这个:
但是,我没有得到好的结果。我想我误会了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_1
和 id_2
的每个组合的每个信息之外,这似乎并没有真正做任何事情。同样,将 [0,1]
的范围添加到 output
中的 window
只会导致错误:
Missing _sortExpr with range-based bounds
有谁知道如何获得与我在 SQL 中相同的结果?
$match
匹配 id_1
和 id_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"
}
])
我正在将一些东西从 SQL 翻译成 MongoDB。
我有一个 Mongo table 设置,其中文档可以包含大量信息。有两个id,id_1
和id_2
。 id_2
的默认值为 -1
。 id_1
和id_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'}
}
}
我在文档中找到了这个:
但是,我没有得到好的结果。我想我误会了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_1
和 id_2
的每个组合的每个信息之外,这似乎并没有真正做任何事情。同样,将 [0,1]
的范围添加到 output
中的 window
只会导致错误:
Missing _sortExpr with range-based bounds
有谁知道如何获得与我在 SQL 中相同的结果?
$match
匹配id_1
和id_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"
}
])