当Mongo中未知元素名称时的项目子文档元素

时间:2015-05-15 02:58:44

标签: json mongodb

我有一个导入Mongo的JSON文件:

{
  "people": {
      "Employee1234": {
          "salary": 10000,
          "dept": "accounting"
       },
       "Employee1235": {
           "salary": 40000,
           "dept": "CEO"
       },
       ...
  }
}

我希望能够找到所有人的独特薪水和部门。

这很棘手,因为people不在[]中,其ID为字段,而是元素是其EID。我正在尝试相当于find({},{people.*.dept}),但你不能做*通配符。如何查询此(鉴于这是现有文档的架构)

1 个答案:

答案 0 :(得分:1)

仅使用具有动态密钥的当前架构的MongoDB查询,这是不可能的。但是,我建议您更改架构,使键成为值并将它们存储在嵌入式文档中。像这种模式的东西很容易查询:

{
    "people": [
        {
            "name": "Employee1234",
            "salary": 10000,
            "dept": "accounting"
        },
            "name": "Employee1235",
            "salary": 40000,
            "dept": "CEO"
        }       
    ]
}

将当前架构转换为上面的架构将使用一些本机JavaScript:

db.collection.find().forEach(function(doc){
    var people = [],
        keys = Object.keys(doc.people);
        obj = {};

    keys.forEach(function(key){
        obj = doc.people[key];
        obj.name = key
        people.push(obj);
    });

    doc.people = people;
    db.collection.save(doc);
});

更改架构后,您现在可以使用 aggregation framework 进行查询。可以找到人们所有独特工资和部门的汇总管道如下:

db.collection.aggregate([
    {
        "$unwind": "$people"
    },
    {
        "$group": {
            "_id": {
                "salary": "$people.salary",
                "department": "$people.dept"
            },
            "count": {
                "$sum": 1
            }
        }
    },
    {
        "$match": { "count": 1 }
    }
]);

对于上面的示例文档,输出将是:

/* 0 */
{
    "result" : [ 
        {
            "_id" : {
                "salary" : 40000,
                "department" : "CEO"
            },
            "count" : 1
        }, 
        {
            "_id" : {
                "salary" : 10000,
                "department" : "accounting"
            },
            "count" : 1
        }
    ],
    "ok" : 1
}