【问题标题】:Find duplicate key in embedded sub document in mongodb在 mongodb 的嵌入子文档中查找重复键
【发布时间】:2015-11-20 18:13:24
【问题描述】:

我正在尝试制作一个查询,让我可以在 MongoDB 的 subdocument 中找到 duplicate 键。

它需要能够查询任意数量的文档,并查看子文档中的哪些键在它们之间重复。我的子文档的键名为attributes,我需要能够针对文档的特定查询并提取它们共享的重复属性键。

编辑: 我忘了提到我不知道属性的名称提前。我需要能够从本质上选择它们共享的不同属性并聚合值。

采集样本:

[
    {
        sku: '123',
        attributes: {
            size: 'L',
            custom: 7
        }
    },
    {
        sku: '456',
        attributes: {
            size: 'M'
        }
    },
    {
        sku: 'abc',
        attributes: {
            material: 'cotton'
            size: 'S'
        }
    }
]

期望的结果(如果可能的话):

{
   size: [' S', 'M', 'L']
}

如果无法获得想要的结果,我至少希望能够找回[ 'size' ]

这个过程需要尽可能优化,我似乎无法得到一个恰到好处的查询来返回我需要的东西,非常感谢任何帮助 =)

这是我目前所拥有的

db.getCollection('myCollection').aggregate([
    { $match: {
            _id: { $in: [ObjectId("55158b0bd6076278295cf022"), ObjectId("55158b0bd6076278295cf021"), ObjectId("55158b0bd6076278295cf01f")   ] }
        }
    },
    { $project: { attributes: 1 }},
    { $group: { _id: '$attributes' } }

])

输出哪些产品:

{
    "result" : [ 
        {
            "_id" : {
                "shirt_size" : "S",
                "shirt_color" : "Blue",
                "custom_attr" : "adsfasdf"
            }
        }, 
        {
            "_id" : {
                "shirt_size" : "M",
                "shirt_color" : "Green"
            }
        }, 
        {
            "_id" : {
                "shirt_size" : "L",
                "shirt_color" : "Red"
            }
        }
    ],
    "ok" : 1.0000000000000000,
    "$gleStats" : {
        "lastOpTime" : Timestamp(1427475045, 1),
        "electionId" : ObjectId("54f7c1edf8e5ff44cec194b6")
    }
}

我觉得它已经接近了,我只是错过了最后一步:(

【问题讨论】:

    标签: mongodb mongodb-query


    【解决方案1】:

    我认为你需要$unwind数组,然后$group它并使用$sum来计算外观,那么所有带有sum > 1的东西都是重复的。

    链接:

    【讨论】:

    • 你能举一个按键分组的例子......不知道键名吗?我认为这似乎是我真正的绊脚石是我不知道属性键名。也许最好的方法就是在代码中获取值并迭代
    • 你不能那样做。您可以在 MongoDB 中对键(不涉及值)执行的唯一操作是 $exists... 你的例子有 sizecustommaterial。在您的应用程序中必须有一些地方可以设置这些键。 ... 另一种方法是将属性的布局更改为 attributes: [ {k: "size", v: "L"}, {k:"custom", v: 7} ] 之类的东西。这实际上取决于您正在执行的查询,哪种解决方案最适合。有时最好的解决方案可能是使用不同的数据排列两次存储数据。
    • 我有种感觉这是不可能的。对于我的特殊用途,存储为键是最有意义的......但它似乎肯定有它的缺点。不过感谢您的帮助!
    【解决方案2】:

    $addToSet(aggregation) 返回一个唯一值数组 - http://docs.mongodb.org/manual/reference/operator/aggregation/addToSet/

    使用以下聚合(获取每个 Doc 的唯一大小):

    db.coll1.aggregate([
    {$unwind : "$testdoc"}, 
    {$group : {_id: "$_id", size: {$addToSet: "$testdoc.attributes.size"}}}
    ])
    

    给出以下结果:

    {
    "result" : [
        {
            "_id" : ObjectId("551621fe6155a7741a0d328a"),
            "size" : [
                "M",
                "L"
            ]
        },
        {
            "_id" : ObjectId("551621fe6155a7741a0d328b"),
            "size" : [
                "L"
            ]
        },
        {
            "_id" : ObjectId("551621fe6155a7741a0d3289"),
            "size" : [
                "S",
                "M",
                "L"
            ]
        }
    ],
    "ok" : 1
    }
    

    以下聚合返回所有文档的唯一大小:

    db.coll1.aggregate([ 
        {$unwind : "$testdoc"}, 
        {$group : 
             {_id: "AllSizes", size: {$addToSet: "$testdoc.attributes.size"}}} ])
    

    结果:

    {
    "result" : [
        {
            "_id" : "AllSizes",
            "size" : [
                "S",
                "M",
                "L"
            ]
        }
    ],
    "ok" : 1
    }
    

    基于以下文档:

    > db.coll1.find().pretty()
    {
    "_id" : ObjectId("551621fe6155a7741a0d3289"),
    "testdoc" : [
        {
            "sku" : "123",
            "attributes" : {
                "size" : "L",
                "custom" : 7
            }
        },
        {
            "sku" : "456",
            "attributes" : {
                "size" : "M"
            }
        },
        {
            "sku" : "abc",
            "attributes" : {
                "material" : "cotton",
                "size" : "S"
            }
        }
    ]
    }
    {
    "_id" : ObjectId("551621fe6155a7741a0d328a"),
    "testdoc" : [
        {
            "sku" : "123",
            "attributes" : {
                "size" : "L",
                "custom" : 7
            }
        },
        {
            "sku" : "456",
            "attributes" : {
                "size" : "M"
            }
        },
        {
            "sku" : "abc",
            "attributes" : {
                "material" : "cotton",
                "size" : "M"
            }
        }
    ]
    }
    {
    "_id" : ObjectId("551621fe6155a7741a0d328b"),
    "testdoc" : [
        {
            "sku" : "123",
            "attributes" : {
                "size" : "L",
                "custom" : 7
            }
        },
        {
            "sku" : "456",
            "attributes" : {
                "size" : "L"
            }
        },
        {
            "sku" : "abc",
            "attributes" : {
                "material" : "cotton",
                "size" : "L"
            }
        }
    ]
    }
    

    【讨论】:

    • 我想我忘了提到我不知道它是“大小”......它可能是“颜色”或任何东西......我需要能够让它抓住不同的价值他们分享。很抱歉没有引起更多关注
    猜你喜欢
    • 2018-09-24
    • 1970-01-01
    • 1970-01-01
    • 2018-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-25
    • 2016-08-25
    相关资源
    最近更新 更多