如何通过MongoDB聚合查询按ID找文档并转置列表字段?
MongoDB单文档内数组字段转置的聚合查询方案
针对你需要将单文档内的results数组转置为键对应数组的需求,可以通过MongoDB聚合管道实现,以下是具体方案及Pymongo、MongoEngine的代码实现:
固定字段场景(已知total_cost、total_time)
如果数组内的字段是固定的,直接使用$match定位文档,再通过$project结合$map提取对应字段的数组即可,这是最高效的方式:
MongoDB聚合管道示例
db.collection.aggregate([ // 按ID筛选目标单文档 { $match: { _id: ObjectId("6345e01473144cec0073ea95") } }, // 构造转置后的结构 { $project: { _id: 0, // 排除原ID字段 total_cost: { $map: { input: "$results", as: "item", in: "$$item.total_cost" } }, total_time: { $map: { input: "$results", as: "item", in: "$$item.total_time" } } } } ])
Pymongo实现代码
from pymongo import MongoClient from bson.objectid import ObjectId # 初始化连接 client = MongoClient("your_mongodb_uri") db = client.your_database collection = db.your_collection # 定义聚合管道 pipeline = [ {"$match": {"_id": ObjectId("6345e01473144cec0073ea95")}}, { "$project": { "_id": 0, "total_cost": {"$map": {"input": "$results", "as": "item", "in": "$$item.total_cost"}}, "total_time": {"$map": {"input": "$results", "as": "item", "in": "$$item.total_time"}} } } ] # 执行查询并获取结果 transposed_result = list(collection.aggregate(pipeline))[0] print(transposed_result)
MongoEngine实现代码
from mongoengine import Document, ListField, EmbeddedDocument, FloatField, ObjectIdField from bson.objectid import ObjectId # 定义文档模型 class ResultItem(EmbeddedDocument): total_cost = FloatField() total_time = FloatField() class TargetDocument(Document): _id = ObjectIdField() results = ListField(EmbeddedDocumentField(ResultItem)) meta = {"collection": "your_collection_name"} # 定义聚合管道 pipeline = [ {"$match": {"_id": ObjectId("6345e01473144cec0073ea95")}}, { "$project": { "_id": 0, "total_cost": {"$map": {"input": "$results", "as": "item", "in": "$$item.total_cost"}}, "total_time": {"$map": {"input": "$results", "as": "item", "in": "$$item.total_time"}} } } ] # 执行聚合查询 result_cursor = TargetDocument.objects.aggregate(*pipeline) transposed_result = next(result_cursor) print(transposed_result)
动态字段场景(数组内字段不固定)
如果results数组内的字段是动态变化的,可以使用更通用的聚合逻辑,自动提取所有字段并转置:
db.collection.aggregate([ { $match: { _id: ObjectId("6345e01473144cec0073ea95") } }, { $project: { _id: 0, transposed: { $arrayToObject: { $map: { // 提取第一个元素的所有字段作为键列表 input: { $objectToArray: { $arrayElemAt: ["$results", 0] } }, as: "field", in: { k: "$$field.k", // 遍历所有结果元素,提取对应键的值组成数组 v: { $map: { input: "$results", as: "item", in: { $arrayElemAt: [{ $objectToArray: "$$item" }, { $indexOfArray: [{ $objectToArray: { $arrayElemAt: ["$results", 0] } }, "$$field"] }] }.v } } } } } } } }, // 将转置后的结构设为根文档 { $replaceRoot: { newRoot: "$transposed" } } ])
内容的提问来源于stack exchange,提问作者Tom McLean
相关产品推荐
相关产品推荐

