gpt4 book ai didi

python - 如何通过计算所有元素并按一个请求进行分组来进行 pymongo 聚合

转载 作者:行者123 更新时间:2023-12-01 07:45:57 25 4
gpt4 key购买 nike

我有一个包含如下字段的集合:

{
"_id":"5cf54857bbc85fd0ff5640ba",
"book_id":"5cf172220fb516f706d00591",
"tags":{
"person":[
{"start_match":209, "length_match":6, "word":"kimmel"}
],
"organization":[
{"start_match":107, "length_match":12, "word":"philadelphia"},
{"start_match":209, "length_match":13, "word":"kimmel center"}
],
"location":[
{"start_match":107, "length_match":12, "word":"philadelphia"}
]
},
"deleted":false
}

我想收集类别中不同的单词并对其进行计数。所以,输出应该是这样的:

{
"response": [
{
"tag": "location",
"tag_list": [
{
"count": 31,
"phrase": "philadelphia"
},
{
"count": 15,
"phrase": "usa"
}
]
},
{
"tag": "organization",
"tag_list": [ ... ]
},
{
"tag": "person",
"tag_list": [ ... ]
},
]
}

这样的管道有效:

def pipeline_func(tag):
return [
{'$replaceRoot': {'newRoot': '$tags'}},
{'$unwind': '${}'.format(tag)},
{'$group': {'_id': '${}.word'.format(tag), 'count': {'$sum': 1}}},
{'$project': {'phrase': '$_id', 'count': 1, '_id': 0}},
{'$sort': {'count': -1}}
]

但它对每个标签发出请求。我想知道如何在一个请求中完成它。感谢您的关注。

最佳答案

如上所述,自 $unwind 以来,问题数据与当前声明的管道进程存在轻微不匹配。只能用于数组,并且问题中出现的标签不是数组

对于问题中提供的数据,您基本上需要这样的管道:

db.collection.aggregate([
{ "$addFields": {
"tags": { "$objectToArray": "$tags" }
}},
{ "$unwind": "$tags" },
{ "$unwind": "$tags.v" },
{ "$group": {
"_id": {
"tag": "$tags.k",
"phrase": "$tags.v.word"
},
"count": { "$sum": 1 }
}},
{ "$group": {
"_id": "$_id.tag",
"tag_list": {
"$push": {
"count": "$count",
"phrase": "$_id.phrase"
}
}
}}
])

再次按照注释,由于 tags 实际上是一个对象,那么您实际上需要什么才能根据它的子键 正如问题所问,是将其本质上转变为项目的数组

$replaceRoot的用法在您当前的管道中似乎表明 $objectToArray在这里合理使用,因为它可以从 MongoDB 3.4 的后续补丁版本中获得,这是您现在应该在生产中使用的最低版本。

那个$objectToArray实际上就像它的名字所说的那样,并生成一个数组(或“列表”,更pythonic),其中的条目分为对。这些本质上是一个对象(或“字典”条目)的“列表”,它们分别具有键kv。第一个管道阶段的输出在提供的文档中如下所示:

{
"book_id": "5cf172220fb516f706d00591",
"tags": [
{
"k": "person",
"v": [
{
"start_match": 209,
"length_match": 6,
"word": "kimmel"
}
]
}, {
"k": "organization",
"v": [
{
"start_match": 107,
"length_match": 12,
"word": "philadelphia"
}, {
"start_match": 209,
"length_match": 13,
"word": "kimmel center"
}
]
}, {
"k": "location",
"v": [
{
"start_match": 107,
"length_match": 12,
"word": "philadelphia"
}
]
}
],
"deleted" : false
}

因此,您应该能够看到如何轻松访问这些 k 值并在分组中使用它们,当然还有 v 也是标准数组。所以这只是两个 $unwind如图所示阶段,然后两个 $group阶段。成为第一$group为了通过按键组合进行收集,第二个是根据主分组键收集,同时将其他累积添加到该条目内的“列表”

当然,上面列表的输出并不完全符合您在问题中的要求,但数据基本上就在那里。您可以选择添加 $addFields$project阶段将 _id 键重命名为最终聚合阶段:

  { "$addFields": {
"_id": "$$REMOVE",
"tag": "$_id"
}}

或者简单地在光标输出上做一些pythonic的事情:

cursor = db.collection.aggregate([
{ "$addFields": {
"tags": { "$objectToArray": "$tags" }
}},
{ "$unwind": "$tags" },
{ "$unwind": "$tags.v" },
{ "$group": {
"_id": {
"tag": "$tags.k",
"phrase": "$tags.v.word"
},
"count": { "$sum": 1 }
}},
{ "$group": {
"_id": "$_id.tag",
"tag_list": {
"$push": {
"count": "$count",
"phrase": "$_id.phrase"
}
}
}}
])

output = [{ 'tag': doc['_id'], 'tag_list': doc['tag_list'] } for doc in cursor]

print({ 'response': output });

最终输出为“列表”,可用于响应:

{
"tag_list": [
{
"count": 1,
"phrase": "philadelphia"
}
],
"tag": "location"
},
{
"tag_list": [
{
"count": 1,
"phrase": "kimmel"
}
],
"tag": "person"
},
{
"tag_list": [
{
"count": 1,
"phrase": "kimmel center"
}, {
"count": 1,
"phrase": "philadelphia"
}
],
"tag": "organization"
}

请注意,使用列表理解方法,您可以更好地控制作为输出的“键”的顺序,因为 MongoDB 本身会简单地附加新的键名称一个投影将现有的键保持在最前面。如果这类事情对你来说很重要的话。但实际上不应该如此,因为所有类似对象/字典的结构都不应该被认为具有任何设置的键顺序。这就是数组(或列表)的用途。

关于python - 如何通过计算所有元素并按一个请求进行分组来进行 pymongo 聚合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56457265/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com