天天看點

python mongodb周遊輸出某字段内容_MongoDb:如何從文檔中擷取字段(子文檔)?

這裡的問題是您目前的資料結構對于查詢來說并不是很好。這主要是因為您使用“keys”來實際表示“datapoints”,雖然它最初看起來似乎是一個合乎邏輯的想法,但實際上卻是一個非常糟糕的實踐。在

是以,與其将“childA”和“childB”指定為對象或“sub document”的鍵,不如将這些“值”指定給結構中的通用鍵名稱:{

"_id:"0,

"firstname":"Tom",

"children" : [

{

"name": "childA",

"toys": [

"batman",

"car",

"train"

],

"movies": [

"Ironman"

"Deathwish"

]

},

{

"name": "childB",

"toys": [

"doll",

"bike",

"xbox",

],

"movies": [

"Frozen",

"Barbie"

]

}

]

}

不是最好的,因為有嵌套數組,這可能是一個潛在的問題,但也有一些解決方法(但稍後),但這裡的要點是,這比在“鍵”中定義資料要好得多。而不一緻命名的“鍵”的主要問題是,MongoDB一般不允許使用任何方式來“通配符”這些名稱,是以您隻能使用命名和“絕對路徑”來通路元素,如下所示:children -> childA -> toys

children -> childB -> toys

簡單地說,這就是“壞”,與此相比:

^{pr2}$

從上面準備的樣本來看,我認為這是一種更好的組織資料的方法。在

即便如此,僅僅擷取一些東西,比如“unique list of movies”,也超出了MongoDB中标準.find()類型查詢的範圍。這實際上需要更多的“文檔操作”,并且在MongoDB的聚合架構中得到了很好的支援。這具有查詢方法中不存在的大量操作功能,并且作為具有上述結構的每個文檔的響應,您可以執行以下操作:db.collection.aggregate([

# De-normalize the array content first

{ "$unwind": "$children" },

# De-normalize the content from the inner array as well

{ "$unwind": "$children.movies" },

# Group back, well optionally, but just the "movies" per document

{ "$group": {

"_id": "$_id",

"movies": { "$addToSet": "$children.movies" }

}}

])

“你現在唯一的回答”中的“電影”隻對應于“你在問什麼”。或者,您可以隻使用$push來建立一個“非唯一”清單。但愚蠢的是,這實際上與此相同:db.collection.find({},{ "_id": False, "children.movies": True })

作為一個“集合範圍”的概念,那麼您可以通過簡單地使用.distinct()方法來簡化這一過程。它基本上根據您提供的輸入形成一個“不同”鍵的清單。這在數組上玩得很好:db.collection.distinct("children.toys")

這實際上是對集合中每個“toys”值的所有“distinct”出現的集合範圍内的分析,并以簡單的“array”形式傳回。在

但對于你現有的結構,它應該有一個解決方案來解釋,但你必須明白,解釋是可怕的。這裡的問題是,通用查詢和聚合方法可用的“本機”和優化方法根本不可用,唯一可用的選項是基于JavaScript的處理。盡管通過“v8”引擎內建,它有點更好,但與本機代碼方法并排比較時,它仍然是一個完全的懶散的。在

是以,從您擁有的“原始”表單(JavaScript表單,函數必須非常容易翻譯”):db.collection.mapReduce(

// Mapper

function() {

var id this._id;

children = this.children;

Object.keys(children).forEach(function(child) {

Object.keys(child).forEach(function(childKey) {

Object.keys(childKey).forEach(function(toy) {

emit(

id, { "toys": [children[childkey]["toys"][toy]] }

);

});

});

});

},

// Reducer

function(key,values) {

var output = { "toys": [] };

values.forEach(function(value) {

value.toys.forEach(function(toy) {

if ( ouput.toys.indexOf( toy ) == -1 )

output.toys.push( toy );

});

});

},

{

"out": { "inline": 1 }

}

)

是以JavaScript評估是一種“可怕的”方法,因為它的執行速度要慢得多,而且您可以看到需要實作的“周遊”代碼。對性能來說是個壞消息,是以不要這麼做。改變結構。在

最後,您可以對其進行不同的模組化,以避免“嵌套數組”的概念。了解“嵌套數組”的唯一真正的問題是,如果不閱讀整個文檔并修改它,“更新”嵌套元素是不可能的。在

是以,$push和$pull方法工作良好。但是使用“positional”$運算符并不起作用,因為“outer”數組索引總是“first”比對的元素。是以,如果這真的是你的問題,那麼你可以這樣做,例如:{

"_id:"0,

"firstname":"Tom",

"childtoys" : [

{

"name": "childA",

"toy": "batman"

}.

{

"name": "childA",

"toy": "car"

},

{

"name": "childA",

"toy": "train"

},

{

"name": "childB",

"toy": "doll"

},

{

"name": "childB",

"toy": "bike"

},

{

"name": "childB",

"toy": "xbox"

}

],

"childMovies": [

{

"name": "childA"

"movie": "Ironman"

},

{

"name": "childA",

"movie": "Deathwish"

},

{

"name": "childB",

"movie": "Frozen"

},

{

"name": "childB",

"movie": "Barbie"

}

]

}

如果您确實需要定期“更新”項,而不僅僅是$push和$pull items,那麼這将是避免嵌套更新問題的一種方法“玩具”和“電影”陣列。在

但這裡的總體資訊是圍繞實際使用的通路模式來設計資料。MongoDB通常不喜歡“嚴格路徑”的東西,因為它能夠查詢或以其他方式靈活地釋出更新。在