gpt4 book ai didi

MongoDB 如何获取子文档属性等于某个值的不同子文档列表?

转载 作者:可可西里 更新时间:2023-11-01 09:29:37 24 4
gpt4 key购买 nike

db.test.insert( 
{
'name': 'outer',
'foos': [
{
'name': 'a',
'type': 'bar',
},
{
'name': 'a',
'type': 'bar',
},
{
'name': 'z',
'type': 'baz',
},
{
'name': 'z',
'type': 'baz',
},
]
}
)

如何获得一个不同的 foos 列表,其中 foo.type 等于 bar

我想找到:

[
{
'name': 'a',
'type': 'bar'
}
]

以下不起作用,而是为所有 foo 返回一个不同的值。

db.test.distinct('foos', {'foos.type': 'bar'})

最佳答案

是的,糟糕!对这里的功能有点误解。这是它返回的内容,我将解释原因:

[
{
"name" : "a",
"type" : "bar"
},
{
"name" : "z",
"type" : "baz"
}
]

所以那里的另一个条目“type”等于“baz”,现在两者都是“不同的”,但你错过了你真正问的。

您确实要求不同的“foos”,这是正确的。但是您也只要求从具有“类型”等于“栏”的数组条目的“文档”中获取它。这不会将内容“过滤”为仅那些数组条目,因此您会得到其他结果。

因此您需要在获取“不同”值之前对内容进行“过滤”。您只能使用 .aggregate() 方法真正做到这一点。和 $filter是这里最好的方法:

db.test.aggregate([
// Match documents
{ "$match": { "foos.type": "bar" } },

// Pre-filter the array
{ "$project": {
"foos": {
"$filter": {
"input": "$foos",
"as": "el",
"cond": {
"$eq": [ "$$el.type", "bar" ]
}
}
}
}},

// Unwind the array
{ "$unwind": "$foos" },

// Group distinct
{ "$group": {
"_id": "$foos"
}}
])

或者在 MongoDB 3.2 之前,但是 2.6 及以上版本你可以交替使用 $map$setDifference :

db.test.aggregate([
// Match documents
{ "$match": { "foos.type": "bar" } },

// Pre-filter the array
{ "$project": {
"foos": {
"$setDifference": [
{ "$map": {
"input": "$foos",
"as": "el",
"in": {
"$cond": [
{ "$eq": [ "$$el.type", "bar" ] },
"$$el",
false
]
}
}}
]
}
}},

// Unwind the array
{ "$unwind": "$foos" },

// Group distinct
{ "$group": {
"_id": "$foos"
}}
])

做同样的事情,$map 处理每个数组元素并返回 mactched 元素或 false$setDiffernce 删除错误的:

最后在 2.6 之前的版本中:

db.test.aggregate([
// Match documents
{ "$match": { "foos.type": "bar" } },

// Unwind the array
{ "$unwind": "$foos" },

// Filter the denormalized array
{ "$match": { "foos.type": "bar" } },

// Group distinct
{ "$group": {
"_id": "$foos"
}}
])

一般原则是只留下匹配“type”等于“bar”的数组条目,理想情况是在使用$unwind 之前“预过滤”数组。减少需要处理的工作,因为之后过滤掉实际上会为每个数组条目创建一个新文档,无论它是否匹配。

无论如何,在某些时候您需要使用 $unwind$group 对数组条目进行“去规范化”以“foos”(子文档)作为主键值返回。

它不是 .distinct() 提供的普通“数组”,但基本上是您“清除”不想考虑的数组条目的方式。

这是要记住的事情,因为正常的查询操作不会“过滤”数组元素,所以类似地 .distinct() 的查询输入也不会这样做,从考虑中删除这些元素是你打算做的。

关于MongoDB 如何获取子文档属性等于某个值的不同子文档列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35123873/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com