我有一个MongoDB集合,其中包含一个颜色数组,如:
myCollection:
{
_id : ...,
"colours" : [
{
"colourpercentage" : "42",
"colourname" : "Blue"
},
{
"colourpercentage" : "32",
"colourname" : "Red"
},
{
"colourpercentage" : "10",
"colourname" : "Green "
}
]
}
我想检索此集合的每个条目的每个不同的colourname,并能够通过搜索过滤它。
我试着与众不同,却没有成功。我进一步搜索,发现聚合可以帮助我。目前我有:
db.getCollection('myCollection').aggregate([
{ "$match": { "colours.colourname": /Gre/ } }, # Gre is my search
{ "$unwind": "$colours" },
{ "$match": { "colours.colourname": /search/ } },
{ "$group": {
"_id": "$colours.colourname"
}}
])
它正在工作,但我得到一个像:
这样的数组{
"result" : [
{
"_id" : "Grey"
},
{
"_id" : "Light Green "
},
{
"_id" : "Light Green"
},
{
"_id" : "Green "
},
{
"_id" : "Green"
}
],
"ok" : 1.0000000000000000
}
我想删除最后有空格的重复条目,并显示如下:
["Grey","Light Green","Green"]
答案 0 :(得分:2)
您可以采用的一种方法是 Map-Reduce 方式,即使JavaScript解释器驱动 mapReduce 比聚合框架稍长一些但是将工作,因为您将使用聚合框架中缺少的一些非常有用的本机JavaScript函数。例如,在map函数中,您可以使用trim()
函数删除colourname
字段中的任何尾随空格,以便您可以发出" cleansed"密钥。
Map-Reduce操作通常具有以下map和reduce函数:
var map = function() {
if (!this.colours) return;
this.colours.forEach(function (c){
emit(c.colourname.trim(), 1)
});
};
var reduce = function(key, values) {
var count = 0;
for (index in values) {
count += values[index];
}
return count;
};
db.runCommand( { mapreduce : "myCollection", map : map , reduce : reduce , out : "map_reduce_result" } );
然后,您可以使用正则表达式查询map_reduce_result
集合以获得结果:
var getDistinctKeys = function (doc) { return doc._id };
var result = db.map_reduce_result.find({ "_id": /Gre/ }).map(getDistinctKeys);
print(result); // prints ["Green", "Grey", "Light Green"]
- 更新 -
要在Python中实现这一点,PyMongo的 API 支持MongoDB的map / reduce引擎的所有功能,因此您可以尝试以下方法:
import pymongo
import re
from bson.code import Code
client = pymongo.MongoClient("localhost", 27017)
db = client.test
map = Code("function () {"
" if (!this.colours) return;"
" this.colours.forEach(function (c){"
" emit(c.colourname.trim(), 1)"
" });"
"};")
reduce = Code("function (key, values) {"
" var count = 0;"
" for (index in values) {"
" count += values[index];"
" }"
" return count;"
" };")
result = db.myCollection.map_reduce(map, reduce, "map_reduce_result")
regx = re.compile("Gre", re.IGNORECASE)
for doc in result.find({"_id": regx}):
print(doc)