仅检索/项目MongoDB集合中嵌套数组中的查询元素

时间:2016-04-20 22:24:53

标签: mongodb aggregation-framework

我已经完成了this popular question。所描述的解决方案都没有真正解决我的问题。我也经历过其他职位,徒劳无功。

我想找到具有查询的特定投影字段(投影字段可以是数组的一部分),该查询由嵌套数组的不同深度处的对象组成。我的文档中的数组嵌套最多可达5个级别。我使用$match$and来组合我的所有条件,使用$elemMatch来嵌套数组。查询部分本身工作正常,它找到了正确的文档。然而问题是在投影所需的字段时(其中一些字段属于深层嵌套数组)

对我的情况不起作用的解决方案及原因:

  1. $filter:从3.2版开始提供。我使用的是3.0版。 $ filter不是一个选项。
  2. $unwind:我的嵌套数组(以下示例中的Array3和Array6)有8000个数组元素。根据{{​​1}}的定义,它将创建一个包含重复数据的单独文档流。这不是我们想要做的事情,因为文件很大并且重复,数千次似乎不是一个好主意。如果我遗漏了$unwind的内容,请告诉我。
  3. $unwind$elemMatch:两者都只返回数组中的一个匹配对象。我希望数组中有多个符合特定条件的对象进行投影。
  4. $ operator:我尝试了in this answer所述的方法。不确定它是否是采用嵌套数组的正确方法。对于没有嵌套数组的简单示例,它(在某种程度上)起作用
  5. 下面是一个示例文档,预期结果和一些接近解决问题的事情,但并不完全。

    示例文档(我的集合中的实际文档。名称已更改,数组元素已减少。我不是这样做的。我正在使用的数据实际上是嵌套的。此外最内层的数组可以拉伸到有8000个元素):< / p>

    $redact

    查询:以下所有<和

    • “DataObj.Community.DataPoints.Person.ItemCount”等于777
    • “DataObj.Community.DataPoints.Houses.MatNumber”等于777
    • “DataObj.Community.DataPoints.Houses.Person.OneTwoDetails.Houses.Rooms.OneTwo123.One1X”Equals 777
    • “DataObj.Community.DataSearching.Houses.Rooms.Clauses.Value”Equals 777

    投影:

    • “DataObj.Community.DataPoints.Person.ItemCount”
    • “DataObj.Community.DataPoints.Houses.MatNumber”
    • “DataObj.Community.DataPoints.Houses.Person.OneTwoDetails.Houses.Rooms.OneTwo123.One1X”
    • “DataObj.Community.DataSearching.Houses.Rooms.Clauses.Value”

    预期结果:

    {
    "Name" : "fa191a58-3c8b-4533-9545-3379e996c0b7", 
    "Type" : "67448a7f-c514-4dc4-9836-4be6f54572a7", 
    "DataObj" : { 
        "Community" : [
            {
                "Name" : "5e6ac308-5e14-4c83-8111-55f87f3bab17", 
                "DataPoints" : {
                    "Person" : {
                        "ItemCount" : 777, 
                        "NameCount" : NumberInt(999), 
                        "LevelCount" : NumberInt(999)
                    }, 
                    "Houses" : [                        
                        {
                            "DoorNumber" : NumberInt(4), 
                            "MatNumber" : 777,
                            "Person" : {
                                "ItemCount" : NumberInt(999), 
                                "NameCount" : NumberInt(999), 
                                "OneTwoDetails" : {
                                    "WholeObj" : {
                                        "OneTwo123" : {
                                            "One1X" : 999.9, 
                                            "One2X" : 999.9, 
                                            "One3X" : 999.9
                                        }
                                    }, 
                                    "Houses" : [
                                        {
                                            "DoorNumber" : NumberInt(999), 
                                            "MatNumber" : NumberInt(999), 
                                            "OneTwo123" : {
                                                "One1X" : 999.9, 
                                                "One2X" : 999.9, 
                                                "One3X" : 999.9
                                            }, 
                                            "Rooms" : [
                                                {
                                                    "LengthX" : NumberInt(999), 
                                                    "LengthY" : NumberInt(999), 
                                                    "OneTwo123" : {
                                                        "One1X" : 777, 
                                                        "One2X" : 999.9, 
                                                        "One3X" : 999.9
                                                    }
                                                }, 
                                                {
                                                    "LengthX" : NumberInt(999), 
                                                    "LengthY" : NumberInt(999), 
                                                    "OneTwo123" : {
                                                        "One1X" : 999.9, 
                                                        "One2X" : 999.9, 
                                                        "One3X" : 999.9
                                                    }
                                                }
                                            ]
                                        }
                                    ]
                                }, 
                                "ApplianceCount" : NumberInt(999), 
                                "UtilityPowerCount" : NumberInt(999), 
                                "UtilityPowerDetails" : [
                                    {
                                        "Name" : "d0f587f8-0a5a-4cd8-aa40-b8ca6e725f27", 
                                        "Range" : 999.9
                                    }, 
                                    { 
                                        "Name" : "76626240-2f58-44d0-8a53-0c161cd6ce58", 
                                        "Range" : 999.9
                                    }
                                ]
                            }
                        }
                    ]
                }, 
                "DataSearching" : {
                    "SearchSequence" : NumberInt(999), 
                    "SearchedDetails" : {
                        "TagX" : 999.9, 
                        "TagY" : 999.9
                    }, 
                    "Houses" : [
                        {
                            "Sequence" : NumberInt(4), 
                            "SearchedDetails" : {
                                "TagX" : 999.9, 
                                "TagY" : 999.9
                            }, 
                            "Rooms" : [
                                {
                                    "Sequence" : NumberInt(999), 
                                    "Clauses" : [
                                        {
                                            "Value" : 777, 
                                            "IsLimited" : true
                                        }, 
                                        {
                                            "Value" : 999.9, 
                                            "IsLimited" : true
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                }
            }
        ]
    }
    }
    

    我使用以下方法取得了部分成功,但我不知道如何使这个工作适用于嵌套数组。

    没有嵌套数组的文档:

    {
    "DataObj" : { 
        "Community" : [
            {
                "DataPoints" : {
                    "Person" : {
                        "ItemCount" : 777
                    }, 
                    "Houses" : [                        
                        {
                            "MatNumber" : 777,
                            "Person" : {
                                "OneTwoDetails" : { 
                                    "Houses" : [
                                        {
                                            "Rooms" : [
                                                {
                                                    "OneTwo123" : {
                                                        "One1X" : 777
                                                    }
                                                }
                                            ]
                                        }
                                    ]
                                }
                            }
                        }
                    ]
                }, 
                "DataSearching" : {
                    "Houses" : [
                        {
                            "Rooms" : [
                                {
                                    "Clauses" : [
                                        {
                                            "Value" : 777
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                }
            }
        ]
    }
    }
    

    采取的方法(在另一个StackOverflow问题中找到):

    { 
    "_id" : ObjectId("57154af04b42aa1fd05fe9fe"), 
    "Element1" : "5e6ac308-5e14-4c83-8111-55f87f3bab17", 
    "Element2" : NumberInt(1),
    "Array1" : [
        {
            "Array1Elem1" : NumberInt(666),  
            "Array1Elem2" : 1999.0,
            "Array1Elem3" : 999,
            "Array1Elem4" : 999
        }, 
        {
            "Array1Elem1" : NumberInt(999), 
            "Array1Elem2" : 999.9,
            "Array1Elem3" : 999,
            "Array1Elem4" : 999         
        }, 
        {
            "Array1Elem1" : NumberInt(999), 
            "Array1Elem2" : 999.9,
            "Array1Elem3" : 999,
            "Array1Elem4" : 999
        }, 
        {
            "Array1Elem1" : NumberInt(999), 
            "Array1Elem2" : 999.9,
            "Array1Elem3" : 999,
            "Array1Elem4" : 999
        }, 
        {
            "Array1Elem1" : NumberInt(444), 
            "Array1Elem2" : 2999,
            "Array1Elem3" : 999,
            "Array1Elem4" : 999
        }
    ]
    }
    

    结果(几乎我需要的。不完全返回所询问的投影字段,但至少它只返回与条件匹配的数组元素。我可以使用它):

    db.collectionName.aggregate(
    { "$match" : { 
      $and : [
      { Array1 : { 
        $elemMatch: {
          "Array1Elem1": {$lt : 999}, 
          "Array1Elem2" : {$gt : 1200} 
          }
        } 
      },
      {
      // other conditions
      }
      ]
      }
    },
    { "$project" : {
      "Array1" : {
        "$setDifference" : [
        { "$map" : {
          "input" : "$Array1", 
          "as" : "element",
          "in" : {
            "$cond" : [
            { "$and" : [
              {"$lt" : ["$$element.Array1Elem1", 999]},
              {"$gt" : ["$$element.Array1Elem2", 1200]}
              ]
            },
            {"$cond" : [1, "$$element", 0]},
            false
            ]
            }
          }},
        [false]
        ]
      }
      }
    })
    

    如果我可以将行为扩展到嵌套数组,我可以使用它。如果有任何其他方法可以实现嵌套数组的投影,请讨论。

0 个答案:

没有答案