2016-09-15 247 views
1

我正在查詢一個嵌套的項目數組的json結構。我想返回整個結構,但只包含符合查詢條件的嵌套項。使用Golang嵌套MongoDB查詢mgo.v2

所以 - 樣本結構是

{ 
    parentId:1, 
    items: [ 
      { 
       field1: 1 
       field2: 2 
      }, 
      { 
       field1: 3 
       field2: 4 
      } 
      ] 
} 

我想用這樣的查詢 - >

db.getCollection('mycollection').find({"items.field1":1, "items.field2":2}) 

這個工作,但也帶來了回老二項目,我希望它實際返回是這樣的 - >

{ 
    parentId:1, 
    items: [ 
      { 
       field1: 1 
       field2: 2 
      } 
      ] 
} 

我已經能夠在MongoDB本身創建一個查詢這實現了我想要的東西 - >

db.getCollection('mycollection').aggregate(
    { $unwind : "$items" }, 
    { $match : { 
    "items.field1": 1, 
    "items.field2": 2, 
    }} 
) 

而是試圖對此進行設置使用mgo.v2它證明了一下母馬的時候。 collection.Find方法似乎不喜歡$ unwind命令,並且似乎無法得到正確的語法來使它與Pipe方法一起工作。

有沒有人有任何建議如何創建?我可以創建字符串並傳遞給執行嗎?

回答

1

您需要的實際流水線涉及使用運算符,該運算符根據指定的條件選擇要返回的數組的子集。它只返回一個只包含符合條件的元素的數組。

在你的情況,你需要運行在聚集操作

db.mycollection.aggregate([ 
    { 
     "$project": { 
      "parentId": 1,   
      "items": { 
       "$filter": { 
        "input": "$items", 
        "as": "item", 
        "cond": { 
         "$and": [ 
          { "$eq": ["$$item.field1", 1] }, 
          { "$eq": ["$$item.field2", 2] } 
         ] 
        } 
       } 
      } 
     } 
    } 
]) 

測試 enter image description here


對於不支持$filter操作MongoDB的版本,可以使用set operators的組合作爲:

db.mycollection.aggregate([ 
    { 
     "$project": { 
      "parentId": 1,   
      "items": { 
       "$setDifference": [ 
        { "$map": { 
         "input": "$items", 
         "as": "item", 
         "in": { 
          "$cond": [ 
           { 
            "$and": [ 
             { "$eq": ["$$item.field1", 1] }, 
             { "$eq": ["$$item.field2", 2] } 
            ] 
           }, 
           "$$item", 
           false 
          ] 
         } 
        }}, 
        [false] 
       ] 
      } 
     } 
    } 
]) 

作爲最後的手段,可以爲操作員產生,它使用更多的存儲器(可能的存儲器帽10%的總存儲器的聚合管線每個陣列條目中的每個文檔的副本使用$unwind操作者),因此也需要時間來生產以及「時間」來處理。您可以運行爲:

db.mycollection.aggregate([ 
    { "$unwind" : "$items" }, 
    { "$match" : { 
     "items.field1": 1, 
     "items.field2": 2, 
    }}, 
    { 
     "$group": { 
      "_id": "$_id", 
      "parentId": { "$first": "$parentId" }, 
      "items": { "$push": "$items" } 
     } 
    } 
]) 

,你可以在氧化鎂運行爲pipeline

pipeline := []bson.M{ 
    bson.M{ "$unwind": "$items" }, 
    bson.M{ 
     "$match": bson.M{ 
      "items.field1": 1, 
      "items.field2": 2 
     } 
    }, 
    bson.M{ 
     "$group": bson.M{ 
      "_id": "$_id", 
      "parentId": bson.M{ "$first": "$parentId" }, 
      "items": bson.M{ "$push": "$items" } 
     } 
    } 
} 
pipe := mycollection.Pipe(pipeline) 
iter := pipe.Iter() 

測試中Robomongo

enter image description here

+0

感謝反饋,但不起作用,我得到以下錯誤 - >不能使用bson.M l迭代(類型bson.M)作爲類型bson.D在數組或片段文字 – P456678

+0

我將bson.D更改爲bson.M編譯,但結果不正確。它根本沒有嵌套的子項目。 – P456678

+0

我也試了這一點 - 管道:= [] {bson.M \t \t bson.M { 「$開卷」: 「$項目」}, \t \t bson.M { 「$匹配」:bson.M { \t \t \t 「items.field1」:bson.M { 「$當量」:1}, \t \t \t 「items.field2」:bson.M { 「$當量」:2}, \t \t}, \t \t}, \t} – P456678

1

參考chridam's answer,我相信那個與$filter可以簡化一下:

c := session.DB("test").C("mycollection") 

pipe := c.Pipe([]bson.M{{ 
    "$project": bson.M{ 
     "parentId": 1, 
     "items": bson.M{ 
      "$filter": bson.M{ 
       "input": "$items", 
       "as": "item", 
       "cond": bson.M{ 
        "$and": []bson.M{ 
         {"$eq": []interface{}{"$$item.field1", 1}}, 
         {"$eq": []interface{}{"$$item.field2", 2}}, 
        }, 
       }, 
      }, 
     }, 
    }, 
}}) 

resp := []bson.M{} 
err = pipe.All(&resp) 

if err != nil { 
    panic(err) 
} 

fmt.Println(resp) 

另用$unwind

c := session.DB("test").C("mycollection") 

pipe := c.Pipe([]bson.M{ 
    {"$unwind": "$items"}, 
    {"$match": bson.M{ 
     "items.field1": 1, 
     "items.field2": 2, 
    }}, 
    {"$group": bson.M{ 
     "_id":  "$_id", 
     "parentId": bson.M{"$first": "$parentId"}, 
     "items": bson.M{"$push": "$items"}, 
    }}, 
}) 

resp := []bson.M{} 
err = pipe.All(&resp) 

if err != nil { 
    panic(err) 
} 

fmt.Println(resp) 

兩個無錯地編譯並返回

[map[ 
    _id:ObjectIdHex(".....") 
    parentId:1 
    items:[map[ 
     field2:2 
     field1:1 
    ]] 
]] 

去1.6,蒙戈3.2