MongoDB 子文档的不同值
MongoDB distinct values on subdocuments
我有一个有点奇怪的数据库结构如下:
我有一个具有普通属性的文档,然后我有一个元数据 属性,它是一个对象数组。
metadata: {[
{
key: [key],
value: [value]
},
...
]}
编辑: 永远不会有元数据子文档有重复键
这样做是为了保留元数据对象的顺序
现在我想获取具有给定键的元数据对象的不同值。
我想使用 MongoDB 找到每个不同的 [value],其中 [key] = "x"。并在数组(不是文档)中返回不同的值
我想这不可能使用 distinct 命令,但是使用聚合管道是否可能,或者我是否必须使用 Map-Reduce?
有什么建议吗?
提前致谢! :)
我猜你是这个意思:
{
"metadata": [
{ "key": "abc", "value": "borf" },
{ "key": "cdc", "value": "biff" }
]
},
{
"metadata": [
{ "key": "bbc", "value": "barf" },
{ "key": "abc", "value": "borf" },
{ "key": "abc", "value": "barf" }
]
}
如果您过滤 "abc" 并获得不同的 "value" 条目,如下所示:
db.collection.aggregate([
{ "$match": { "metadata.key": "abc" } },
{ "$unwind": "$metadata" },
{ "$match": { "metadata.key": "abc" } },
{ "$group": {
"_id": "$metadata.value"
}}
])
甚至更好:
db.collection.aggregate([
{ "$match": { "metadata.key": "abc" } },
{ "$redact": {
"$cond": {
"if": { "$eq": [ { "$ifNull": [ "$key", "abc" ] }, "abc" ] },
"then": "$$DESCEND",
"else": "$$PRUNE"
}
}},
{ "$unwind": "$metadata" },
{ "$group": {
"_id": "$metadata.value",
"count": { "$sum": 1 }
}}
])
基本上会给出:
{ "_id": "barf", "count": 1 },
{ "_id": "borf", "count": 2 }
但是 不可能 这只是一个 "barf" 和 "borf" 的数组。 distinct()
方法只做一个键数组,但它也非常有限。因此它只能这样做:
db.collection.distinct("metadata.value",{ "metadata.key": "abc" })
[ "biff", "borf", "barf" ]
结果是不正确的。所以只需从上面获取 "document" 结果并应用一些 "post processing":
db.collection.aggregate([
{ "$match": { "metadata.key": "abc" } },
{ "$redact": {
"$cond": {
"if": { "$eq": [ { "$ifNull": [ "$key", "abc" ] }, "abc" ] },
"then": "$$DESCEND",
"else": "$$PRUNE"
}
}},
{ "$unwind": "$metadata" },
{ "$group": {
"_id": "$metadata.value"
}}
]).map(function(doc) {
return doc._id;
})
结果是一个仅包含不同值的普通数组:
[ "borf", "barf" ]
我有一个有点奇怪的数据库结构如下:
我有一个具有普通属性的文档,然后我有一个元数据 属性,它是一个对象数组。
metadata: {[
{
key: [key],
value: [value]
},
...
]}
编辑: 永远不会有元数据子文档有重复键
这样做是为了保留元数据对象的顺序
现在我想获取具有给定键的元数据对象的不同值。
我想使用 MongoDB 找到每个不同的 [value],其中 [key] = "x"。并在数组(不是文档)中返回不同的值
我想这不可能使用 distinct 命令,但是使用聚合管道是否可能,或者我是否必须使用 Map-Reduce?
有什么建议吗?
提前致谢! :)
我猜你是这个意思:
{
"metadata": [
{ "key": "abc", "value": "borf" },
{ "key": "cdc", "value": "biff" }
]
},
{
"metadata": [
{ "key": "bbc", "value": "barf" },
{ "key": "abc", "value": "borf" },
{ "key": "abc", "value": "barf" }
]
}
如果您过滤 "abc" 并获得不同的 "value" 条目,如下所示:
db.collection.aggregate([
{ "$match": { "metadata.key": "abc" } },
{ "$unwind": "$metadata" },
{ "$match": { "metadata.key": "abc" } },
{ "$group": {
"_id": "$metadata.value"
}}
])
甚至更好:
db.collection.aggregate([
{ "$match": { "metadata.key": "abc" } },
{ "$redact": {
"$cond": {
"if": { "$eq": [ { "$ifNull": [ "$key", "abc" ] }, "abc" ] },
"then": "$$DESCEND",
"else": "$$PRUNE"
}
}},
{ "$unwind": "$metadata" },
{ "$group": {
"_id": "$metadata.value",
"count": { "$sum": 1 }
}}
])
基本上会给出:
{ "_id": "barf", "count": 1 },
{ "_id": "borf", "count": 2 }
但是 不可能 这只是一个 "barf" 和 "borf" 的数组。 distinct()
方法只做一个键数组,但它也非常有限。因此它只能这样做:
db.collection.distinct("metadata.value",{ "metadata.key": "abc" })
[ "biff", "borf", "barf" ]
结果是不正确的。所以只需从上面获取 "document" 结果并应用一些 "post processing":
db.collection.aggregate([
{ "$match": { "metadata.key": "abc" } },
{ "$redact": {
"$cond": {
"if": { "$eq": [ { "$ifNull": [ "$key", "abc" ] }, "abc" ] },
"then": "$$DESCEND",
"else": "$$PRUNE"
}
}},
{ "$unwind": "$metadata" },
{ "$group": {
"_id": "$metadata.value"
}}
]).map(function(doc) {
return doc._id;
})
结果是一个仅包含不同值的普通数组:
[ "borf", "barf" ]