2016-09-25 122 views
1

我是Mongo(一名SQL人員優先)並且在其他人設置的應用程序中工作的新手。我有這樣的記錄,加上更多的信息:更新中的Mongo查詢

City: 
    name: "name" 
    State: ObjectId({id here}) 
    slug: "slug" 
    images: [images] 
    ... 

而且國家也有與它塞文本字段。我想爲相關城市的城市創建一個新條目。所以這將是一個陣列與圖像,slu,,狀態slu,和名稱。我曾嘗試以下,但我最終查詢信息的stateSlug:

db.getCollection('city').find(
{ 
    $or: 
     [ 
      {"name": "Camden"}, 
      {"name": "Virginia Beach"}, 
      {"name": "Annapolis"} 
     ] 
},{images:1, slug:1, state:1, name:1} 
).forEach(function(city){ 
    db.city.update({"name" : "Lewes"}, {$push:{'relatedCities': 
     { "images":city.images, 
      "slug":city.slug, 
      "name":city.name, 
      "stateSlug":db.state.find(city.state,{slug:1,_id:0}) 
     } 
    }}) 
}) 

有沒有一種方法,我可以讓這個查詢的工作?我有一個用於excel文件和python腳本的查詢名稱,可以將這種格式的信息輸出到一個js文件中執行,如果我能弄清楚如何使它工作的話。謝謝你的幫助!

回答

1

你需要採取包括運行使用以下步驟管道聚合管道(順序給出)的方法:

1)$match以過濾進入管道的文件。考慮使用$in運營商而不是$or如果您的表達涉及equality checks for the value of the same field。這與SQL的WHERE子句類似,例如,代替

SELECT name, images, state, slug 
WHERE name in ('Camden', 'Virginia Beach', 'Annapolis') 

SELECT name, images, state, slug 
WHERE 
    (name = 'Camden') OR 
    (name = 'Virginia Beach') OR 
    (name = 'Annapolis') 

2)$lookup做左外連接到在同一數據庫中的unsharded收集從「接合」在文檔過濾收集這是state集合進行處理。 $lookup階段在輸入文檔的state字段與_id字段與「已加入」收集狀態的文檔之間執行相等匹配。

3)$unwind - 從以前$lookup管道的結果的新領域是一個數組,所以你需要一個$unwind階段添加到您的管道,以便您可以拼合陣列,因爲它需要作爲非規範化領域進一步處理。

4)$group管道步驟將所有文檔分組並創建一個數組relatedCities,其中包含來自前一個管道的字段。管道運算符類似於SQL的GROUP BY子句。在SQL中,除非使用任何聚合函數,否則不能使用GROUP BY。同樣的,你也必須在MongoDB中使用聚合函數。您可以閱讀關於彙總功能here的更多信息。

您需要創建陣列的累加器運算符爲$push

5)$project最後階段,然後用來選擇或重命名從前面的管道文件的屬性 - 類似於您將與SQL SELECT條款做什麼。要使用字符串文字創建新字段,您需要運算符,它與SQL的ASALIAS關鍵字類似。


這裏有一點要注意的是執行管道,MongoDB的管道運營商進入對方時。這裏的「管道」採用Linux的含義:操作員的輸出成爲後面的操作員的輸入。每個操作員的結果都是一個新的文檔集合。所以蒙戈執行上述的管道如下:

collection | $match | $lookup | $unwind | $group | $project => result 

現在,當你運行在蒙戈外殼這種聚合管道,其結果將是,當你使用toArray()方法對cursor你得到一個數組通過調用aggregate()方法返回city集合。

然後,您可以創建首家通過零指數,這是具有聚合領域的新city文件訪問的唯一元素,結果數組中的city集合中的新城市條目,並在使用save()方法城市收藏堅持文件。

下面的例子說明上述概念:

var pipeline = [ 
     { 
      "$match": { 
       "name": { "$in": ["Camden", "Virginia Beach", "Annapolis"] } 
      } 
     }, 
     { 
      "$lookup": { 
       "from": "state", 
       "localField": "state", 
       "foreignField": "_id", 
       "as": "states" 
      } 
     }, 
     { "$unwind": "$states" }, 
     { 
      "$group": { 
       "_id": null, 
       "relatedCities": { 
        "$push": { 
         "images": "$images", 
         "slug": "$slug", 
         "name": "$name", 
         "stateSlug": "$states.slug" 
        } 
       } 
      } 
     }, 
     { 
      "$project": { 
       "_id": 0, 
       "name": { "$literal": "Lewes" }, 
       "relatedCities": 1 
      } 
     }  
    ], 
    newCity = db.city.aggregate(pipeline).toArray()[0]; 

db.city.save(newCity);