2016-08-20 84 views
5

我有一個文檔集合,其中「tags」字段從空格分隔的標籤列表切換到單個標籤數組。我想將以前的空格分隔字段更新爲所有數組,如新的傳入數據。將Mongo中的字段從String轉換爲Array

我也遇到了$ type選擇器的問題,因爲它將類型操作應用到單個數組元素,這是字符串。因此按類型過濾只是返回所有內容。

如何將第一個示例中的每個文檔轉換爲第二個示例的格式?

{ 
    "_id" : ObjectId("12345"), 
    "tags" : "red blue green white" 
} 
{ 
    "_id" : ObjectId("54321"), 
    "tags" : [ 
     "red", 
     "orange", 
     "black" 
    ] 
} 
+0

優秀的問題..我試過,但無法解決它在mongodb ..然後我擡頭看着mongodb傑拉和它的工作進展.. https://jira.mongodb.org/browse/SERVER-6773 – user641887

+0

@ user641887 jira已經關閉。但是可以在沒有$ split的情況下在MongoDB中執行此操作。唯一的問題是性能。 – styvane

回答

2

我們不能用$type運營商在這裏過濾我們的文件,因爲我們的數組中的元素的類型是「字符串」和文檔中提到:

當應用到陣列,$ type匹配任何指定BSON類型的內部元素。例如,當匹配$ type:'array'時,如果該字段具有嵌套數組,則該文檔將匹配。它不會返回字段本身是數組的結果。

幸運的是,MongoDB還提供了$exists運算符,它可以在這裏與數字數組索引一起使用。

現在我們該如何更新這些文件?

那麼,從MongoDB版本< = 3.2,我們唯一的選擇是mapReduce(),但首先讓我們看看即將發佈的MongoDB的另一種選擇。

從MongoDB 3.4開始,我們可以$project我們的文檔,並使用$split運算符來將我們的字符串拆分爲一個子字符串數組。

請注意,要僅分割字符串中的那些「標籤」,我們需要邏輯處理來分割僅字符串的值。這裏的條件是$eq,當該字段的$type等於"string"時,其評估爲true。順便說一下$type這裏是3.4中的新功能。

最後,我們可以使用$out流水線階段操作符覆蓋舊集合。 但是我們需要在$project階段中明確指定包含其他字段。

db.collection.aggregate(
    [ 
     { "$project": { 
      "tags": { 
       "$cond": [ 
        { "$eq": [ 
         { "$type": "$tags" }, 
         "string" 
        ]}, 
        { "$split": [ "$tags", " " ] }, 
        "$tags" 
       ] 
      } 
     }}, 
     { "$out": "collection" } 
    ] 
) 

隨着mapReduce,我們需要使用Array.prototype.split()發出子陣列中我們地圖功能。我們還需要使用「查詢」選項來過濾我們的文檔。從那裏,我們將需要迭代爲「標籤」使用使用bulkWrite()方法新批量操作在3.2「結果」陣列和$set新值或現在棄用Bulk()如果我們在2.6或3.0,如圖here.

db.collection.mapReduce(
    function() { emit(this._id, this.tags.split(" ")); }, 
    function(key, value) {}, 
    { 
     "out": { "inline": 1 }, 
     "query": { 
      "tags.0": { "$exists": false }, 
      "tags": { "$type": 2 } 
     } 
    } 
)['results'] 
相關問題