Pymongo中根据值长度查询集合和文档
Querying the collection and documents based on the value length in Pymongo
假设我的数据库给我一个查询结果:
{'_id': ObjectId('5c99d76a32aacf180485c3b3'),
'text': 'ILLUSTRATION : 1\nFind the quotient and remainder q and r for the pairs of positive integers given below:\n(i) 23,4\n(ii) 81,3\n(iii) 12,5\nUTION.\n',
'text2': '',
'parent': None,
'repost': 3,
'time': datetime.datetime(2010, 5, 9, 16, 5, 27, 838000)}
我想获取前 1000 个文档,其中 text
的长度或 text2
的长度 >=5:
我可以通过 Python 做到这一点,但这样做是愚蠢的:
objects = []
i = 0
for obj in db.essays.find():
if len(obj['text']>=5) or len(obj['text2']>=5):
objects.append(obj)
i+=1
if i==1000:
break
我知道这很愚蠢。
如果我有完全匹配,我可以使用 limit(1000)
,但我不知道如何根据值长度获取文档。
编辑:
我以某种方式设法做了一个 PATCH 作为:
{ "$or":[{"$expr": { "$gt": [ { "$strLenCP": "$text" }, 5 ]}},
{"$expr": { "$gt": [ { "$strLenCP": "$text2" }, 5 ]}},
{"$expr": { "$gt": [ { "$strLenCP": "$text3" }, 5 ]}},
]}
但是当我使用AND
操作获取文档时,当所有文本长度都小于3时,它会抛出错误:
{ "$and":[{"$expr": { "$lt": [ { "$strLenCP": "$text" }, 5 ]}},
{"$expr": { "$lt": [ { "$strLenCP": "$text2" }, 5 ]}},
{"$expr": { "$lt": [ { "$strLenCP": "$text3" }, 5 ]}},
]}
它适用于 limit(2)
但失败 >2 并抛出错误:
`OperationFailure: $strLenCP requires a string argument, found: null`
您可以使用 $strLenCP
聚合管道。
这里是示例代码说明:
objects = []
for obj in db.essays.aggregate([
{
"$project": {
"text1Len": {
"$strLenCP": "$text"
},
"text2Len": {
"$strLenCP": "$text2"
},
"docRoot": "$$ROOT",
}
},
{
"$match": {
"$or": [
{"text1Len": {"$gte": 5}},
{"text2Len": {"$gte": 5}},
]
}
},
{
"$limit": 1000
},
{
"$replaceRoot": {
"newRoot": "$docRoot"
}
},
]):
objects.append(obj)
您可以将管道与 strLenCP
一起使用
db.collection.aggregate([
{
"$match": {
"$expr": {
"$or": [
{
"$gte": [
{
"$strLenCP": {
"$ifNull": [
"$text",
""
]
}
},
5
]
},
{
"$gte": [
{
"$strLenCP": {
"$ifNull": [
"$text2",
""
]
}
},
5
]
}
]
}
}
},
{
"$limit": 1000
}
])
但是,如果您真的关心性能之上的问题,最好的方法是预处理该信息:
{
'_id': ObjectId('5c99d76a32aacf180485c3b3'),
'text': 'ILLUSTRATION : 1\nFind the quotient and remainder q and r for the pairs of positive integers given below:\n(i) 23,4\n(ii) 81,3\n(iii) 12,5\nUTION.\n',
'text2': '',
'parent': None,
'repost': 3,
'time': datetime.datetime(2010, 5, 9, 16, 5, 27, 838000),
'text_len': 100,
"text2_len": 0
}
所以现在一个简单的查询就足够了:
db.essays.find({"$or": [{"text_len": {"$gte": 5}}, {"text2_len": {"$gte": 5}}]}).limit(1000)
假设我的数据库给我一个查询结果:
{'_id': ObjectId('5c99d76a32aacf180485c3b3'),
'text': 'ILLUSTRATION : 1\nFind the quotient and remainder q and r for the pairs of positive integers given below:\n(i) 23,4\n(ii) 81,3\n(iii) 12,5\nUTION.\n',
'text2': '',
'parent': None,
'repost': 3,
'time': datetime.datetime(2010, 5, 9, 16, 5, 27, 838000)}
我想获取前 1000 个文档,其中 text
的长度或 text2
的长度 >=5:
我可以通过 Python 做到这一点,但这样做是愚蠢的:
objects = []
i = 0
for obj in db.essays.find():
if len(obj['text']>=5) or len(obj['text2']>=5):
objects.append(obj)
i+=1
if i==1000:
break
我知道这很愚蠢。
如果我有完全匹配,我可以使用 limit(1000)
,但我不知道如何根据值长度获取文档。
编辑: 我以某种方式设法做了一个 PATCH 作为:
{ "$or":[{"$expr": { "$gt": [ { "$strLenCP": "$text" }, 5 ]}},
{"$expr": { "$gt": [ { "$strLenCP": "$text2" }, 5 ]}},
{"$expr": { "$gt": [ { "$strLenCP": "$text3" }, 5 ]}},
]}
但是当我使用AND
操作获取文档时,当所有文本长度都小于3时,它会抛出错误:
{ "$and":[{"$expr": { "$lt": [ { "$strLenCP": "$text" }, 5 ]}},
{"$expr": { "$lt": [ { "$strLenCP": "$text2" }, 5 ]}},
{"$expr": { "$lt": [ { "$strLenCP": "$text3" }, 5 ]}},
]}
它适用于 limit(2)
但失败 >2 并抛出错误:
`OperationFailure: $strLenCP requires a string argument, found: null`
您可以使用 $strLenCP
聚合管道。
这里是示例代码说明:
objects = []
for obj in db.essays.aggregate([
{
"$project": {
"text1Len": {
"$strLenCP": "$text"
},
"text2Len": {
"$strLenCP": "$text2"
},
"docRoot": "$$ROOT",
}
},
{
"$match": {
"$or": [
{"text1Len": {"$gte": 5}},
{"text2Len": {"$gte": 5}},
]
}
},
{
"$limit": 1000
},
{
"$replaceRoot": {
"newRoot": "$docRoot"
}
},
]):
objects.append(obj)
您可以将管道与 strLenCP
一起使用db.collection.aggregate([
{
"$match": {
"$expr": {
"$or": [
{
"$gte": [
{
"$strLenCP": {
"$ifNull": [
"$text",
""
]
}
},
5
]
},
{
"$gte": [
{
"$strLenCP": {
"$ifNull": [
"$text2",
""
]
}
},
5
]
}
]
}
}
},
{
"$limit": 1000
}
])
但是,如果您真的关心性能之上的问题,最好的方法是预处理该信息:
{
'_id': ObjectId('5c99d76a32aacf180485c3b3'),
'text': 'ILLUSTRATION : 1\nFind the quotient and remainder q and r for the pairs of positive integers given below:\n(i) 23,4\n(ii) 81,3\n(iii) 12,5\nUTION.\n',
'text2': '',
'parent': None,
'repost': 3,
'time': datetime.datetime(2010, 5, 9, 16, 5, 27, 838000),
'text_len': 100,
"text2_len": 0
}
所以现在一个简单的查询就足够了:
db.essays.find({"$or": [{"text_len": {"$gte": 5}}, {"text2_len": {"$gte": 5}}]}).limit(1000)