Distinct / Aggregation查询Mongodb数组,修剪尾随空格

时间:2015-05-25 12:48:36

标签: mongodb nosql

我有一个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"]

1 个答案:

答案 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)