针对多个正则表达式匹配过滤数组

时间:2014-08-05 22:37:45

标签: python regex mongodb pymongo

我想搜索MongoDB,以便只获得在密钥元素的某些配置中找到所有x的结果。这是this previous question的延续。

collected = []                              # Initialize an empty list

for x in input:                             # Iterate over input
  collected.append(re.compile(x))           # Append re.compile object to list

cursor = db.collection.find({"key": {"$all": collected}})

现在它返回输入列表元素出现在提供的键的任何元素中的所有文档。如何只获得输入列表元素出现在键元素中的结果?

例如

input = ['A', 'B', 'C', 'D']

它将返回带有

的文档
key = ['AHBKCOD', 'NDSI']

但不是

key = ['A', 'B', 'C', 'D', 'AB']

返回匹配元素会很棒'AHBKCOD'也是直接的。

1 个答案:

答案 0 :(得分:1)

Mongo Shell示例

设置测试数据:

> db.test.insert({'key': ['AHBKCOD', 'NDSI']})
> db.test.insert({'key': ['A', 'B', 'C', 'D', 'AB']})

您当前的查询确实与两个记录都匹配,因此$all不是我们想要的运算符:

> db.test.find({"key": {"$all": [/A/, /B/, /C/, /D/]}}, {'_id': 0})
{ "key" : [  "AHBKCOD",  "NDSI" ] }
{ "key" : [  "A",  "B",  "C",  "D",  "AB" ] }

要匹配包含一组正则表达式的字符串并重新构造返回对象,您需要使用aggregation framework。此查询所需的操作包括$unwind$match,$ and$project

> db.test.aggregate([{"$unwind": "$key"}, 
                     {"$match": {"$and": [{"key": /A/}, 
                                          {"key": /B/}, 
                                          {"key": /C/}, 
                                          {"key": /D/}]}}, 
                     {"$project": {"_id": 0, "key": "$key"}}])

这将只返回您想要的密钥:

{ "result" : [ { "key" : "AHBKCOD" } ], "ok" : 1 }

如果您运行的是mongo 2.6或更高版本,那么聚合函数将返回一个游标,就像查询查询一样。 2.6以下,您将获得一个包含顶级密钥的文档,result和'确定'。要提取结果数组,您可以将["result"]添加到查询的末尾。

[ { "key" : "AHBKCOD" } ]

转向Python

将此转换为Python的工作很少,因为JSON (和mongo扩展JSON)可以使用而不会改变太多,因为它们通常是值Python结构(字典,列表) 特别是如果你小心引用键。 Python没有像/A/那样的正则表达式文字,所以我们需要进行一次更改,转换为re.compile(r'A')

input = ['A', 'B', 'C', 'D']

collected = [{"key": re.compile(x)} for x in input] 

query = [{"$unwind": "$key"}, 
         {"$match": {"$and": collected}}, 
         {"$project": {"_id": 0, "key": "$key"}}]

result = db.test.aggregate(query)["result"]

我假设您在这里使用的是2.6以下版本的MongoDB。

print result
[{u'key': u'AHBKCOD'}]

对于值列表,您可以使用列表推导:

print [res['key'] for res in result]
[u'AHBKCOD']