以下是
pictures
MongoDB 集合的摘录:
[
{
"_id": "57582b6b",
"source": "integration",
"url": "https://example.com/images/51/landscapes-polar.xml",
"pictures": [
{
"name": "pines",
"version": "2"
},
{
"name": "penguins",
"version": "1"
},
{
"name": "pineapple",
"version": "7"
}
]
},
{
"_id": "57582b6d",
"source": "customer",
"url": "https://example.com/images/15/nature.xml",
"pictures": [
{
"name": "mountains",
"version": "2"
},
{
"name": "pines",
"version": "1"
}
]
},
{
"_id": "57582b6c",
"source": "qa",
"url": "https://example.com/image/32/landscapes.xml",
"pictures": [
{
"name": "alps",
"version": "1"
},
{
"name": "pineapple",
"version": "7"
},
{
"name": "pines",
"version": "3"
}
]
}
]
我主要关心的是从嵌套的
names
数组内部找到特定的 pictures
。当找到与部分查询字符串匹配的名称时,它们应保留在 pictures
数组中,并与 pictures
的父数组一起显示。使用 PyMongo 库,我能够使用此函数检索查询的数据:
import re
from flask import Flask, jsonify
from controller.database import client, database_name, temp_collection
app = Flask(__name__)
db = client[database_name]
collection = db[temp_collection]
@app.route('/component/find/<picture_name>', methods=['GET'])
def get_component(picture_name):
pattern = re.compile(picture_name, re.IGNORECASE)
pipeline = [
{"$unwind": "$pictures"},
{"$match": {"pictures.name": {"$regex": pattern}}},
{"$group": {
"_id": "$_id",
"url": {"$first": "$url"},
"source": {"$first": "$source"},
"pictures": {"$addToSet": "$pictures"},
"root": {"$first": "$$ROOT"}
}},
{"$replaceRoot": {
"newRoot": {
"$mergeObjects": ["$root", {"pictures": "$pictures"}]
}
}},
{"$project": {
"_id": {"$toString": "$_id"},
"url": 1,
"source": 1,
"pictures": 1
}}
]
result = list(collection.aggregate(pipeline))
if result:
return jsonify(result)
else:
return jsonify({"message": "Component with picture '{}' not found.".format(picture_name)}), 404
if __name__ == "__main__":
app.run(debug=True)
但是,检索到的数据仅包含单元素
pictures
数组,而不是放入所有匹配的对象。
换句话说,这就是我想要得到的:
[
{
"_id": "57582b6b",
"source": "integration",
"url": "https://example.com/51/landscapes-polar.xml",
"pictures": [
{
"name": "pines",
"version": "2"
},
{
"name": "pineapple",
"version": "7"
}
]
},
{
"_id": "57582b6d",
"source": "customer",
"url": "https://example.com/15/nature.xml",
"pictures": [
{
"name": "pines",
"version": "1"
}
]
},
{
"_id": "57582b6c",
"source": "qa",
"url": "https://example.com/image/32/landscapes.xml",
"pictures": [
{
"name": "pineapple",
"version": "7"
},
{
"name": "pines",
"version": "3"
}
]
}
]
这就是我现在得到的:
[
{
"_id": "57582b6b",
"source": "integration",
"url": "https://example.com/51/landscapes-polar.xml",
"pictures": [
{
"name": "pines",
"version": "2"
}
]
},
{
"_id": "57582b6d",
"source": "customer",
"url": "https://example.com/15/nature.xml",
"pictures": [
{
"name": "pines",
"version": "1"
}
]
},
{
"_id": "57582b6c",
"source": "qa",
"url": "https://example.com/image/32/landscapes.xml",
"pictures": [
{
"name": "pineapple",
"version": "7"
}
]
}
]
如何确保所有匹配的
pictures
对象都被推送到正确的数组? (使用 $push
代替 $addToSet
会返回相同的结果。)
使用 Mongo Playground,我能够逐步构建查询,并发现删除一些标记会得到我想要的内容。 Flask 应用程序应该这样设置:
import re
from flask import Flask, jsonify
from controller.database import client, database_name, temp_collection
app = Flask(__name__)
db = client[database_name]
collection = db[temp_collection]
@app.route('/component/find/<picture_name>', methods=['GET'])
def get_component(picture_name):
pattern = re.compile(picture_name, re.IGNORECASE)
pipeline = [
{"$unwind": "$pictures"},
{"$match": {"pictures.name": {"$regex": pattern}}},
{"$group": {
"_id": {"$toString": "$_id"}, # convert _id to str
"url": {"$first": "$url"},
"source": {"$first": "$source"},
"pictures": {"$addToSet": "$pictures"}
}}
]
result = list(collection.aggregate(pipeline))
if result:
return jsonify(result)
else:
return jsonify({"message": "Component with picture '{}' not found.".format(picture_name)}), 404
if __name__ == "__main__":
app.run(debug=True)