2014年2月28日 星期五

MongoDB 開發筆記 - 使用 find / aggregate: $match 找尋必有或必無某屬性(property/element/field)的資料

話說 MongoDB 真是越用越順手,也唯有這樣才能體會大家為何對他驚歎 :P 在處理資料時,由於 schema free style,有時分析資料時,希望每筆資料都要有某個屬性才來處理,或是資料不能有某個屬性:

db.collection.find( { property: {$ne: null }} )
db.collection.find( { property: null} )


如果 property 的內容物是一個 array,如 { "property":[ ... ] } ,這時想要要求此 array 個數要大於 1 時,則可以改用 "$where" 語法(據說效率較慢,但 it's works !):

db.collection.find( { "$where": "this.property && this.property > 1" } )

然而,在 aggregate 的 $match 卻無法使用 "$where" 語法,可惜了點,會有以下錯誤訊息:

failed: exception: $where is not allowed inside of a $match aggregation expression

此外,就算分析出來,還是有要分析到 array 裡頭項目,又發現 aggregate 有 $unwind 的功能!效果就是幫你把 array 裡頭的資料一筆筆輸出:

db.collection.aggregate([
{
$match: {
property: { $ne : null }
}
},
{
$unwind: "$property"
},
{
$group: {
_id: "$property.name",
count: {
$sum: 1
}
}
}
])


單筆資料如:

{
"id": "client",
"date": "date",
"property":
[
{ "name": "ios", "version": 1 } ,
{ "name": "android", "version": 1 } ,
{ "name": "ios", "version": 2 }
]
}


假設資料就上述一筆,透過 aggregate $unwind 總輸出會是 property.length 個數:

{ "id": "client", "date": "date", "name": "ios", "version": 1 }
{ "id": "client", "date": "date", "name": "android", "version": 1 }
{ "id": "client", "date": "date", "name": "ios", "version": 2 }

沒有留言:

張貼留言