【问题标题】:What is the correct way to query in mongodb for the array of documents?在 mongodb 中查询文档数组的正确方法是什么?
【发布时间】:2017-07-02 13:25:58
【问题描述】:

以下是mongodb中的集合

{
"name" : "Tom" ,
"occupation" : "employee" ,
"data" : [
        {
            "owns" : "Television" ,
            "company" : "xyz"   
        },
        {
            "owns" : "Television" ,
            "company" : "abc"   
        },
        {
            "owns" : "laptop" ,
            "company" : "abc"
        } ,
        {
            "owns" : "Television" ,
            "company" : "xyz"
        }

        ]   
}

当我查询时

   db.exp.find({"data.owns" : "Television"}) 

mongodb 返回结果集中包含 "owns" :"laptop" 的文档。

当我查询时

   db.exp.find({"data.owns": "Television"},{_id: 0, data: {$elemMatch: {"owns": "Television"}}}) 

结果仅显示找到第一个匹配“电视”的数据字段中的一个文档

我如何查询以获得汤姆拥有电视的所有 3 个文档,不包括笔记本电脑文档。 预期结果

 [
        {
            "owns" : "Television" ,
            "company" : "xyz"   
        },
        {
            "owns" : "Television" ,
            "company" : "abc"   
        },

        {
            "owns" : "Television" ,
            "company" : "xyz"
        }

 ]  

注意:在这个例子中我只提到了数据字段中的 4 个文档,而原始集合有超过 50 个文档。 对不起我糟糕的英语:)。

【问题讨论】:

    标签: mongodb mongodb-query aggregation-framework


    【解决方案1】:

    这可以使用aggregation.来完成

    • $unwind data 数组。
    • 使用$match 阶段过滤owns 值为Television 的文档。
    • $group 阶段用于重新组合您的文档。
    • $project 阶段可重塑您的文档。
    db.exp.aggregate(
        [
            { "$unwind": "$data" }, 
            { "$match": { "data.owns": "Television" }}, 
            {
                "$group": {
                              "_id": {
                                         "name": "$name",
                                         "occupation": "$occupation"
                                     }, 
                              "data": { "$push": "$data" }
                          }
            }, 
            {
                "$project": {
                                "name": "$_id.name", 
                                "occupation": "$_id.occupation", 
                                "data": 1, 
                                "_id": 0
                            }
            }
        ]
    )
    

    结果:

    {
            "data" : [
                    {
                            "owns" : "Television",
                            "company" : "xyz"
                    },
                    {
                            "owns" : "Television",
                            "company" : "abc"
                    },
                    {
                            "owns" : "Television",
                            "company" : "xyz"
                    }
            ],
            "name" : "Tom",
            "occupation" : "employee"
    }
    

    【讨论】:

      【解决方案2】:

      假设您在集合中有两个文档exp

      [
        {
        "name" : "Tom" ,
        "occupation" : "employee" ,
        "data" : [ { "owns" : "Television" , "company" : "xyz" },
          { "owns" : "Television" , "company" : "abc" },
          { "owns" : "laptop" , "company" : "abc" } ,
          { "owns" : "Television" , "company" : "xyz" } ]   
        },
        {
        "name" : "Jerry" ,
        "occupation" : "employee" ,
        "data" : [ { "owns" : "Mobile" , "company" : "xyz" },
          { "owns" : "Mobile" , "company" : "abc" },
          { "owns" : "laptop" , "company" : "abc" } ,
          { "owns" : "Laptop" , "company" : "xyz" } ]   
        }
      ]
      

      然后用你的查询db.exp.find({"data.owns" : "Television"}),你会得到

      { "_id" : 101, 
      "name" : "Tom", 
      "occupation" : "employee", 
      "data" : [ 
        { "owns" : "Television", "company" : "xyz" }, 
        { "owns" : "Television", "company" : "abc" }, 
        { "owns" : "laptop", "company" : "abc" }, 
        { "owns" : "Television", "company" : "xyz" } 
       ] 
      }
      

      由于第一个文档的字段owns等于Television,结果将是完整的第一个文档。(包括那些具有owns而不是Television的字段) 第二个文档不会成为结果的一部分,因为它没有任何 owns 字段的值为 Television

      $elemMatch 只会返回一个文档。

      http://docs.mongodb.org/manual/reference/operator/projection/elemMatch/

      如果您只希望数组中的这三个对象以Television 作为其值,那么您可以使用游标来存储查询的整个结果(在我们的例子中只有一个文档)。

      var x = db.authors.find({"data.owns": "Television"},{_id: 0, "data.owns": 1})
      

      现在,使用 for 每个循环仅获取具有 owns 且值为 Television 的文档。

      【讨论】:

      • 不是在外部应用程序中过滤文档,我们不能在数据库本身中完成这项任务吗?
      • 您可以为此目的使用聚合。对不起,我没有在答案中提到。
      猜你喜欢
      • 2021-09-23
      • 2019-09-21
      • 2012-08-15
      • 2019-06-14
      • 1970-01-01
      • 1970-01-01
      • 2019-08-01
      • 2018-10-05
      • 1970-01-01
      相关资源
      最近更新 更多