MongDB是一种开源的文档型数据库(document database),它可以通过自己BSON存储JSON形式的数据。因为以documents的形式存储在数据库中,起初进行CRUD时候用起来比较麻烦,比如要查询doc中子集的子集。经过一段时间的探索和努力以后,发现通过aggregate方法,完完全全体现啦它的灵活性和扩展性。
下面举个查询的例子:
如下图,一个collection中包含了一个复杂的document:
document={ "_id" : ObjectId("58046aee430e9c11109c3de2"), "texts" : [ { "time" : "2016-10-17-14-00", "number" : "12345678988", "name" : "", "io" : 0.0 }, { "time" : "2016-10-17-14-00", "number" : "12345678988", "name" : "", "io" : 0.0 }, { "time" : "2016-10-17-14-00", "number" : "12345678988", "name" : "", "io" : 0.0 }, { "time" : "2016-10-17-14-00", "number" : "12345678988", "name" : "", "io" : 0.0 } ], "calls" : [ { "time" : "2016-10-17-14-00", "number" : "12345678988", "name" : "", "io" : 1.0, "duration" : 60.0 }, { "time" : "2016-10-17-14-00", "number" : "12345678988", "io" : 1.0, "duration" : 60.0 } ] }
要对document中两个field的value数组进行按时间筛选,返回符合要求的list。仅用MongoDB官网那些基础的find()之类的方法无法达到要求,可以通过aggregate的project ,unwind方法实现:
info = document.aggregate([ {"$project": { data['type']:{ "$filter":{ "input": "$" + data['type'], "as": "item", "cond": {"$and":[ {"$lte": ["$$item.time", end]}, {"$gte": ["$$item.time", start]} ]} } } }}, {"$unwind": "$" + data['type']}, {"$project": type_format(data['type'])} ]) def type_format(type): r = {"_id": 0} for k in document[type][0]: r[k] = '$' + type + '.' + k return r
data['type'] 为所要查询的field。
MongoDB 的aggregate方法有一个pipeline的概念,可以将doc数据经过层层处理,向后传送。
如上例,
1、先通过第一个project将所要的field按filter条件的values都筛出来,作为向下的输入;
2、再通过unwind使其作为当先的context(替代之前的document)
3、最后通过project将所要求的格式list输出。
Over.