具有嵌套文档的Mongodb $ lookup

时间:2018-11-14 18:43:25

标签: mongodb mongodb-query aggregation-framework mongodb-compass

我正在尝试使用mongo的查找创建联接。我有这三个收藏。

orderTracking

DECLARE @TableXML TABLE(Col1 int primary key, Col2 xml) 
Insert into @TableXML values ( 1,
'<CookedUP>
  <Evenement Calcul="16">
    <Cookie xmlns="http://services.ariel.morneausobeco.com/2007/02" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
      <AlternateOptionTypeCodes />
      <Cash>0</Cash>
      <CashInterest>0</CashInterest>
      <CashSource>Undefined</CashSource>
      <Code>A</Code>
      <SmallAmount>0</SmallAmount>
      <SmallAmountType>Undefined</SmallAmountType>
    </Cookie>
    <Cookie xmlns="http://services.ariel.morneausobeco.com/2007/02" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
      <AlternateOptionTypeCodes />
      <Cash>1</Cash>
      <CashInterest>2</CashInterest>
      <CashSource>Undefined</CashSource>
      <Code>B</Code>
      <SmallAmount>1</SmallAmount>
      <SmallAmountType>1</SmallAmountType>
    </Cookie>
  </Evenement>
</CookedUP> '
)


;WITH XMLNAMESPACES ('http://services.ariel.morneausobeco.com/2007/02' AS ns)
SELECT b.Col1
        --Also include the namespaces here with ns: for each "field" you are after contained within Cookie
       ,XmlCol.value('(./ns:SmallAmount)[1]', 'int') AS SmallAmount
       ,XmlCol.value('(./ns:Cash)[1]', 'int') AS Cash
       ,XmlCol.value('(./ns:Code)[1]', 'nvarchar(10)') AS Code
       ,XmlCol.value('(./ns:CashSource)[1]', 'nvarchar(10)') AS CashSource
FROM @TableXML b
CROSS APPLY b.Col2.nodes('/CookedUP/Evenement/ns:Cookie') AS x(XmlCol) --ns, the namespace, only at Cookie node.

locationType

{   
    _id: ObejctId("59fb7815b3b8429f4750b0df"),
    itemName : "Hamam Soap",
    TrackLocation: [{locationId: 1, at:"2017-10-11"},
            {locationId: 2,at:"2017-10-13"}],
    userId : 12,
    price: 20
} 

用户

{
    _id: ObejctId("59b2111345cb72345a35fefd"),
    locationId : 1
    productTypeName: "Warehouse"
},{
    _id: ObejctId("59af8ce445cb72345a35feea"),
    locationId : 2
    productTypeName: "On Transit"
}

并尝试将其简化为此类输出。

{
    _id: ObejctId("59a504eb6171b554c02292a9"),
            "user ID":12,
    "userName" : "Shahabaz Shafi",
    "dateOfBirth" : "1992-01-01",
    "addres": {
        "country" : "India",
        "state" : "Karnataka",
        "city" :  "Bengaluru"
    }

}

编辑:2018年11月15日更新输出

对输出列进行了一些更改

{
"userName" : "Shahabaz Shafi",
"userId":12,
"dateOfBirth" : "1992-01-01",
"country" : "India",
"state" : "Karnataka",
"city" :  "Bengaluru"

"locationType" : [ {productTypeName: "Warehouse",at:"2017-10-11"}, {productTypeName: "On Transit",at:"2017-10-13"}]
}

我该如何处理?

PS:我也在使用指南针

1 个答案:

答案 0 :(得分:2)

您可以在mongodb 3.6 及更高版本

中使用以下聚合
db.User.aggregate([
  { "$lookup": {
    "from": "orderTracking",
    "let": { "userId": "$userId" },
    "pipeline": [
      { "$match": { "$expr": { "$eq": ["$userId", "$$userId"] }}},
      { "$unwind": "$TrackLocation" },
      { "$lookup": {
        "from": "locationType",
        "let": { "location": "$TrackLocation.locationId" },
        "pipeline": [
          { "$match": { "$expr": { "$eq": ["$locationId", "$$location"] }}}
        ],
        "as": "locationType"
      }},
      { "$project": {
        "_id": 0,
        "productTypeName": { "$arrayElemAt": ["$locationType.productTypeName", 0] },
        "at": "$TrackLocation.at"
      }}
    ],
    "as": "locationType"
  }},
  { "$replaceRoot": { "newRoot": { "$mergeObjects": ["$addres", "$$ROOT"] }}},
  { "$project": { "addres": 0 }}
])

Output

[
  {
    "_id": ObjectId("59a504eb6171b554c02292a9"),
    "city": "Bengaluru",
    "country": "India",
    "dateOfBirth": "1992-01-01",
    "locationType": [
      {
        "at": "2017-10-11",
        "productTypeName": "Warehouse"
      },
      {
        "at": "2017-10-13",
        "productTypeName": "On Transit"
      }
    ],
    "state": "Karnataka",
    "userId": 12,
    "userName": "Shahabaz Shafi"
  }
]