如何在pymongo中正确设计正则表达式?

时间:2019-05-29 15:30:25

标签: python regex python-3.x mongodb pymongo

我使用python 3.7.1(默认值,2018年12月14日,19:28:38)和pymongo 3.7.2。

在mongodb中,这有效:

db.collection.find(
    {$and:[
    {"field":{$regex:"bon?"}},
    {"field":{$not:{$regex:"bon souple"}}},
    {"field":{$not:{$regex:"bon léger"}}}
    ]}
    )

所以在pymongo中,我做的与之相同:

db.collection.find(
    {"$and":[
    {"field":{"$regex":"bon?"}},
    {"field":{"$not":{"$regex":"bon souple"}}},
    {"field":{"$not":{"$regex":"bon léger"}}}
    ]}
    )

但是它表示pymongo.errors.OperationFailure: $regex has to be a string

因此,我按照建议的here进行了尝试:

liste_reg=[
{'field': {'$regex': {'$not': re.compile('bon souple')}}}, 
{'field': {'$regex': {'$not': re.compile('bon léger')}}}, 
{'field': {'$regex': re.compile('bon?')}}
]
rslt=list(
    db.collection.find({"$and":liste_reg})
)

我注意到,即使没有特殊字符,它也表示相同的错误:

liste_reg=[
{'field': {'$regex': {'$not': re.compile('bon souple')}}} #where no special char is present
]
rslt=list(
    db.collection.find({"$and":liste_reg})
)

所以我尝试将"/"用作:

liste_reg=[
{'field': {'$regex': {'$not':'/bon souple/'}}} #where no special char is present
#even tried re.compile('/bon souple/')
]
rslt=list(
    db.collection.find({"$and":liste_reg})
)

同样的错误pymongo.errors.OperationFailure: $regex has to be a string仍然发生。

我该怎么办?

我对解决方案研究的一些更新

问题的核心似乎在于$not,因为当我这样做时:

liste_reg=[{'field': {'$regex': 'bon?'}}]
rslt=list(
    db.collection.find({"$and":liste_reg})
)
len(rslt)#gives 23 013, what is ok.

没有错误。

一些样品

根据Emma的要求,我可以举一个示例,它将在mongo中明确显示我的请求。 通常,我必须在该字段中具有以下模式:

  • trèsléger
  • léger
  • bonléger
  • bon
  • bon汤
  • souple
  • Très汤粉
  • 柯兰特
  • 响亮
  • trèsLourd
  • 喜欢

对我来说主要的问题是我的蜘蛛不能正确解析,因为我没有为此编写足够强大的脚本。 我得到的结果不是仅仅获得“ bon”,而是得到这样的结果:

{"_id":"ID1",
"field":"bon\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\tnon",
...}

这是许多其他错误解析之间的示例。 因此,这就是为什么我想要以"bon?"开头而不是"bon souple""bon léger"开头的结果的原因,因为它们具有正确的值,而没有\n\t

因此作为示例:

[{"_id":"ID1",
"field":"bon\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\tnon"},
{"_id":"ID2",
"field":"bon\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tpremière"},
{"_id":"ID3",
"field":"bon\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t2ème"},
{"_id":"ID4",
"field":"bon souple"},
{"_id":"ID5",
"field":"bon léger"}]

3 个答案:

答案 0 :(得分:2)

尝试使用带有否定前瞻性的字符串文字。只要您在'bon'之后有回车符(\ r),下面的示例就可以工作。

import re
bon = re.compile(r'bon(?=\r)')
db.collection.find({'field': bon})

答案 1 :(得分:2)

我只是遇到了同样的问题。

尝试这样做:

liste_reg=[
{'field': {'$not': re.compile('bon souple')}}, 
{'field': {'$not': re.compile('bon léger')}}, 
{'field': {'$regex': re.compile('bon?')}}
]
rslt=list(
    db.collection.find({"$and":liste_reg})
)

我刚刚删除了查询的$regex部分。

背景

我尝试做{item["type"]: {"$not": item['name']}},而pymongo返回了$not needs a regex or a document错误。

因此,我尝试:{item["type"]: {"$not": {"$regex": item['name']}}},pymongo返回了$not cannot have a regex错误。

我找到了这样的https://stackoverflow.com/a/20175230/9069964,这终于对我有用:

item_name = item["name"]
{item["type"]: {"$not": re.compile(item_name)}}

我不得不放弃“ $ regex”部分,并给“ $ not”我的正则表达式内容。

答案 2 :(得分:0)

在这里,我们也许可以解决此问题,甚至无需使用$not功能。例如,如果我们不希望bon souplebon léger后面没有空格,则可以使用类似于以下内容的表达式:

bon

DEMO

我不太确定我们要在此处提取的内容,但是我只是猜测也许我们想在"bon[^\s].+" 之间滑动bon值,而不用空格。

此外,我们可能希望研究正则表达式查询要求并根据需要调整表达式,例如转义或使用捕获组:

"

或:

(bon[^\s].+)

或:

"(bon[^\s].+)"

或:

\"(bon[^\s].+)\" 

DEMO

RegEx电路

jex.im可视化正则表达式:

enter image description here


我不确定这是否是我们想要的,或者是否有意义,但是根据此documentation,我们可以尝试使用:

([\s\S]*?)\"(bon[^\s].+)\"

或:

{ name: { $regex: /([\s\S]*?)\"(bon[^\s].+)\"/, $options: "mi" } }

db.collection.find

{ name: { $regex: '([\s\S]*?)\"(bon[^\s].+)\"', $options: "mi" } }

或:

db.collection.find({"field":{ $regex: /(bon[^\s].+)/, $options: "mi" }})

参考:

PyMongo $in + $regex

Performing regex Queries with pymongo