【问题标题】:python - sort mongodb by the value of one keypython - 按一个键的值对mongodb进行排序
【发布时间】:2016-04-22 15:06:08
【问题描述】:

我有一个具有以下数据结构的集合:

[{name: "123", category: "A"},
 {name: "456", category: "B"},
 {name: "789", category: "A"},
 {name: "101", category: "C"}]

我希望能够根据category 的值对它们进行排序,方法是指定哪个先出现。例如,按照 B->C->A 的顺序对查询进行排序,结果将是:

[{name: "456", category: "B"},
 {name: "101", category: "C"},
 {name: "123", category: "A"},
 {name: "789", category: "A"}]

mongo 查询 API 有什么好的方法吗?我正在使用mongoengine

【问题讨论】:

  • 这可能与this question 重复我不能投票结束,因为这个问题的答案没有被赞成或接受,所以添加了一个答案。

标签: python mongodb pymongo aggregation-framework mongoengine


【解决方案1】:

最好的方法是使用.aggregate() 方法和$cond 条件运算符在$project 阶段为您的文档添加权重,然后使用$sort 聚合运算符按权重对文档进行排序。

pipeline = [{'$project': {'category': 1,
               'name': 1,
               'w': {'$cond': [{'$eq': ['$category', 'B']},
                               1,
                               {'$cond': [{'$eq': ['$category', 'C']},
                                          2,
                                          3]
                               }]
                    }
            }},
            {'$sort': {'w': 1}}
]

Model.aggregate(*pipeline)

使用 PyMongo 的演示

>>> import pprint
>>> import pymongo
>>> client = pymongo.MongoClient()
>>> collection = client['test']['collection']
>>> pipeline = [{'$project': {'category': 1,
...                    'name': 1,
...                    'w': {'$cond': [{'$eq': ['$category', 'B']},
...                                    1,
...                                    {'$cond': [{'$eq': ['$category', 'C']},
...                                               2,
...                                               3]
...                                    }]
...                         }
...                 }},
...                 {'$sort': {'w': 1}}
...     ]
>>> pprint.pprint(list(collection.aggregate(pipeline=pipeline)))
[{'_id': ObjectId('571caa930e4f55302502a361'),
  'category': 'B',
  'name': '456',
  'w': 1},
 {'_id': ObjectId('571caa930e4f55302502a363'),
  'category': 'C',
  'name': '101',
  'w': 2},
 {'_id': ObjectId('571caa930e4f55302502a360'),
  'category': 'A',
  'name': '123',
  'w': 3},
 {'_id': ObjectId('571caa930e4f55302502a362'),
  'category': 'A',
  'name': '789',
  'w': 3}]

【讨论】:

    【解决方案2】:

    我认为在 MongoDB 中仍然无法提供自定义排序功能:

    作为一种解决方法,您可以在 Python 中进行排序,将类别映射到实际用于对文档进行排序的数值:

    from pprint import pprint
    
    weights = {
        "A": 2,
        "B": 0,
        "C": 1
    }
    
    docs = db.col.find()
    pprint(sorted(docs, key=lambda item: weights.get(item["category"])))
    

    【讨论】:

    • 其实这个jira已经很老了。我想知道为什么它仍然是开放的,因为从 MongoDB 版本 2.6 开始,您可以使用 $cond 运算符来执行此服务器端。无论如何,这将解决问题,但效率低于使用 C++ 编码的本机 API 的解决方案
    • @user3100115 哦,哇,不知道。很好的答案!谢谢。
    • @user3100115 使用aggregate() 的好例子,但是你介意用C++ 编写的mongo 的API 比python 更高效吗?
    • @tropicalfish 在像 C++ 这样的静态类型语言中编写良好的代码大多数时候比像 Python 这样的动态类型语言快,为什么?答案超出了这里的范围。另请注意,某些操作在服务器端处理得更好,这正是 MongoDB 提供 sort 方法、$sort 更新运算符和 $sort 聚合管道运算符的原因。
    猜你喜欢
    • 2015-04-14
    • 1970-01-01
    • 2011-03-25
    • 1970-01-01
    • 2023-03-25
    • 2013-09-14
    • 1970-01-01
    • 2021-09-23
    • 2020-12-04
    相关资源
    最近更新 更多