MongoDB在子文档上的不同值

时间:2015-08-04 09:39:27

标签: mongodb mapreduce aggregation-framework distinct-values

我有一个奇怪的数据库结构如下:

我有一个具有普通属性的文档,然后我有一个元数据属性,它是一个对象数组。

metadata: {[
  {
     key: [key],
     value: [value]
  },
  ...
 ]}

修改:永远不会有具有重复键的元数据子文档

这样做是为了保留元数据对象的顺序

现在我想获得具有给定键的元数据对象的不同值。

我希望使用MongoDB找到[key] =“x”的每个不同的[value]。并且在数组(而不是文档)中返回不同的值

我想使用distinct命令是不可能的,但这可能是使用聚合管道还是我必须使用Map-Reduce?

有什么建议吗?

提前致谢! :)

1 个答案:

答案 0 :(得分:3)

我认为你的意思是:

{
    "metadata": [
        { "key": "abc", "value": "borf" },
        { "key": "cdc", "value": "biff" }
    ]
},
{
    "metadata": [
        { "key": "bbc", "value": "barf" },
        { "key": "abc", "value": "borf" },
        { "key": "abc", "value": "barf" }
    ]
}

如果您过滤“abc”并获得不同的“值”条目,请执行以下操作:

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" ]

结果不正确。因此,只需从上面获取“文档”结果并应用一些“后期处理”:

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" ]