【问题标题】:MongoDb: $sort by $inMongoDb: $sort by $in
【发布时间】:2013-01-16 23:47:10
【问题描述】:

我正在使用 $in 运算符运行 mongodb find 查询:

collection.find({name: {$in: [name1, name2, ...]}})

我希望按照与我的名称数组相同的顺序对结果进行排序:[name1, name2, ...]。我如何做到这一点?

注意:我是通过 pymongo 访问 MongoDb,但我认为这并不重要。

编辑:由于在 MongoDb 中无法实现这一点,我最终使用了典型的 Python 解决方案:

names = [name1, name2, ...]
results = list(collection.find({"name": {"$in": names}}))
results.sort(key=lambda x: names.index(x["name"]))

【问题讨论】:

  • 你的意思是要先包含name1的记录,然后是包含name2的记录?
  • 是的,完全正确。在目前的情况下,名称是唯一的,但这不相关,是吗?
  • 目前无法通过正常查询实现
  • 你是什么意思,独特的?

标签: python mongodb sorting pymongo


【解决方案1】:

您可以使用从即将发布的 3.4 版(2016 年 11 月)开始的聚合框架来实现这一点。

假设您想要的顺序是数组order=["David", "Charlie", "Tess"],您可以通过此管道进行操作:

m = { "$match" : { "name" : { "$in" : order } } };
a = { "$addFields" : { "__order" : { "$indexOfArray" : [ order, "$name" ] } } };
s = { "$sort" : { "__order" : 1 } };
db.collection.aggregate( m, a, s );

"$addFields" 阶段是 3.4 中的新功能,它允许您在不知道所有其他现有字段的情况下将"$project" 新字段添加到现有文档。新的"$indexOfArray" 表达式返回给定数组中特定元素的位置。

此聚合的结果将是符合您条件的文档,按照输入数组order 中指定的顺序,并且文档将包括所有原始字段,以及一个名为__order 的附加字段

【讨论】:

    【解决方案2】:

    不可能。 $in 运算符检查存在。该列表被视为集合。

    选项:

    • 为 name1 ... nameN 拆分多个查询或以相同方式过滤结果。 更多名称 - 更多查询。
    • 使用 itertools groupby/ifilter。在这种情况下 - 为每个文档添加“排序优先级”标志,并将 name1 匹配到 PREC1,将 name2 匹配到 PREC2,......,然后按 PREC 排序,然后按 PREC 分组。

    如果您的收藏在“名称”字段上有索引 - 选项 1 更好。 如果没有索引,或者由于写入/读取比率高而无法创建索引 - 选项 2 适合您。

    【讨论】:

      【解决方案3】:

      Vitaly 是正确的,使用 find 无法做到这一点,但可以通过聚合来实现:

      db.collection.aggregate( [ { $match: { name: {$in: [name1, name2, ...]} }, { $project: { 'name': 1, 'name1': { $eq: [ 'name1', '$name' ] }, 'name2': { $eq: [ 'name2', '$name' ] } } }, { $sort: { 'name1': 1, 'name2': 1 } } ] )

      在 2.6.5 上测试

      我希望这会向其他人暗示正确的方向。

      【讨论】:

        猜你喜欢
        • 2017-05-18
        • 1970-01-01
        • 1970-01-01
        • 2016-11-15
        • 2012-11-22
        • 2015-10-07
        • 1970-01-01
        • 2021-12-17
        • 1970-01-01
        相关资源
        最近更新 更多