Python 使用pymongo&;对来自MongoDB的结果中的项进行聚合和计数;瓶子
我试图在Flask环境中使用pymongo从MongoDB返回一个简单的JSON结果。以下是我正在做的:Python 使用pymongo&;对来自MongoDB的结果中的项进行聚合和计数;瓶子,python,mongodb,mongodb-query,pymongo,aggregation-framework,Python,Mongodb,Mongodb Query,Pymongo,Aggregation Framework,我试图在Flask环境中使用pymongo从MongoDB返回一个简单的JSON结果。以下是我正在做的: def myResults(): myCollection = db["my_data"] results = list(myCollection.find({},{"ID":1,"Response":1,"_id":0})) return jsonify(results=results) 当我这样做时,我得到以下结果。FYI“ID”基本上是一个组成的唯一标识符 {
def myResults():
myCollection = db["my_data"]
results = list(myCollection.find({},{"ID":1,"Response":1,"_id":0}))
return jsonify(results=results)
当我这样做时,我得到以下结果。FYI“ID”
基本上是一个组成的唯一标识符
{
"result": [
{
"ID": 1,
"Response": "A"
},
{
"ID": 4,
"Response": "B"
},
{
"ID": 3,
"Response": "A"
},
]
} // and so on...
我想汇总特定ID的所有响应并显示计数。我猜是这样的(或者如果有更好的方法):
{
"result": [
{
"ID": 1,
"A": 2,
"B": 1,
"C": 5,
"Total": 8
},
{
"ID": 4,
"A": 0,
"B": 5,
"C": 18,
"Total": 23
},
{
"ID": 3,
"A": 12,
"B": 6,
"C": 8,
"Total": 26
},
]
}
StackOverflow上有人建议使用aggregate()
。但这对我来说并不管用
allResults = surveyCollection.aggregate([
{"$unwind": result },
{"$group": {"_id": result.ID, "A": {"$sum": 1}, "B": {"$sum": 1}}},
{"$group": {"_id": None, "result": {"$push": {"ID": "$ID", "A": "$A", "B": "$B"}}}}
])
return jsonify(allResults)
我得到一个错误:AttributeError:'list'对象没有属性“ID”
仅仅使用
find()
或count()
没有更简单的方法吗?将result.ID替换为“result.ID”。如果没有引号,python将查找变量result.ID(该变量不存在),而不是向服务器发送文本字符串“result.ID”。聚合框架引用所有带有$
前缀的字段名。这不是“python”代码,而是“聚合管道”操作,因此它只是一个要转换为BSON的数据结构
allResults = surveyCollection.aggregate([
{ "$group": {
"_id": {
"ID": "$ID",
"type": "$Response"
},
"count": { "$sum": 1 },
}},
{ "$group": {
"_id": "$_id.ID",
"A": { "$sum": { "$cond": [{ "$eq": [ "$_id.type", "A" ]}, "$count", 0 ] } },
"B": { "$sum": { "$cond": [{ "$eq": [ "$_id.type", "B" ]}, "$count", 0 ] } },
"C": { "$sum": { "$cond": [{ "$eq": [ "$_id.type", "C" ]}, "$count", 0 ] } },
"Total": { "$sum": "$count" }
}}
])
return jsonify(allResults)
这就产生了你给我们的三份文件,结果如下:
{ "_id" : 1, "A" : 1, "B" : 0, "C" : 0, "Total" : 1 }
{ "_id" : 4, "A" : 0, "B" : 1, "C" : 0, "Total" : 1 }
{ "_id" : 3, "A" : 1, "B" : 0, "C" : 0, "Total" : 1 }
所以你在最后开始做正确的事情,但是在中间偏离了轨道。
无法在这里执行的是在聚合框架中“动态”创建字段,因此需要指定所有必需的“属性”,并使用所示条件进行测试。如果您不能接受这种格式,那么需要使用mapReduce。就我个人而言,我会这样做,这更简单:
allResults = surveyCollection.aggregate([
{ "$group": {
"_id": {
"ID": "$ID",
"type": "$Response"
},
"count": { "$sum": 1 }
}},
{ "$group": {
"_id": "$_id.ID",
"results": {
"$push": {
"type": "$_id.type",
"count": "$count"
}
},
"Total": { "$sum": "$count" }
}}
])
return jsonify(allResults)
输出格式不同,但基本信息相同且简单:
{ "_id" : 1, "results" : [ { "type" : "A", "count" : 1 } ], "Total" : 1 }
{ "_id" : 4, "results" : [ { "type" : "B", "count" : 1 } ], "Total" : 1 }
{ "_id" : 3, "results" : [ { "type" : "A", "count" : 1 } ], "Total" : 1 }
顺便说一句,这实际上看起来像是来自一个聚合结果,因此可能是时候重新访问创建源代码了。Find()返回一个游标,其中包含在查询中收集的所有数据,这是一个简单的命令,您只需迭代它并获取信息。你在这么做吗?@Urbester是的,我过去用
find()
迭代并获取我想要的信息,但我想知道我是否可以附加count()
以解决上述问题。感谢修复。有道理。但不幸的是,我没有看到结果。我将此作为我的结果{“ok”:1.0,“result:[]}
。另外,:
在“$add”
之后,由于某种原因导致语法错误。@mapr您似乎试图从上一个聚合阶段继续进行,实际上每个步骤似乎都是作为一个单独的问题来问的。这混淆了你自己和其他人的背景。我建议提前在组中添加您以前的“计数”阶段(或者您可能有不同的字段名),确保添加所有字段,因为聚合管道阶段只接收输出的内容。下次你问的时候,从你的源数据开始。这样做只会误导你,而且肯定会做得更好。但这是另一个问题。@mapr你说的是哪一个原始问题?如果我使用如上所示的数据创建了一个新集合(实际上是单个文档),那么我将得到您使用如上所示的查询所显示的结果。正如我所说,你显然在做一些不同的事情。@mapr让我们重新开始好的,从我认为是你原始数据的最近的信息来源开始。我相信你可能做得对。但我在这里没有做什么不同的事情。我在仔细检查我的工作,然后再打给你。虽然我知道这行代码是正确的,但我觉得这行代码可能是导致问题的原因:results=list(myCollection.find({},{ID:1,“Response:1,{u ID:0}))
这会导致pymongo.errors.OperationFailure
。我认为$
必须在结果
字符串之前出现。