【问题标题】:Sort by array's last element mongodb按数组的最后一个元素排序 mongodb
【发布时间】:2017-06-22 06:48:58
【问题描述】:

我试图按上次交互对文档进行排序。 meta_data.access_times 是一个数组,每次用户交互时都会更新,新的日期对象附加到数组的最后一个元素。有没有办法按数组的最后一个元素排序?

尝试 1:

private Aggregation makeQuery(String userId) {
     return newAggregation(
          match(Criteria.where("user_id").is(userId)),
          sort(Sort.Direction.DESC, "$meta_data.access_times"),
          group(Fields.fields().and("first_name", "$meta_data.user_data.first_name").and("last_name", "$meta_data.user_data.last_name").and("profile_pic", "$meta_data.user_data.profile_pic").and("user_id", "$user_id").and("access_times", "$meta_data.access_times"))
      );
    }

尝试2:

 private Aggregation makeQuery(String userId) {
        return newAggregation(
            match(Criteria.where("user_id").is(user_id)),
            group(Fields.fields().and("first_name", "$meta_data.user_data.first_name").and("last_name", "$meta_data.user_data.last_name").and("profile_pic", "$meta_data.user_data.profile_pic").and("user_id", "$user_id")).max("$meta_data.access_times").as("access_time"),
            sort(Sort.Direction.DESC, "access_time")
        );
    }

文档中的示例 meta_data 数组

"meta_data" : { "access_times" : [ 
            ISODate("2017-06-20T14:04:14.910Z"), 
            ISODate("2017-06-22T06:27:32.210Z"), 
            ISODate("2017-06-22T06:27:35.326Z"), 
            ISODate("2017-06-22T06:31:28.048Z"), 
            ISODate("2017-06-22T06:36:19.664Z"), 
            ISODate("2017-06-22T06:37:00.164Z")
        ] }

【问题讨论】:

  • 好吧,我们似乎遗漏了您的文档实际外观的任何表示。愿意与我们分享吗?
  • @NeilLunn 更新
  • 所以“最后一个”总是附加的,因此是“最新的”?通常只是检查。
  • @NeilLunn 是的!
  • 你期望输出什么? group 把我扔了,因为不清楚会发生什么。主要是因为它无效。如何显示整个文档(仅 2 或 3 个)以及您期望获得的查询结果。这将比您的查询尝试更清楚地解释。日期部分我已经明白了。

标签: arrays mongodb sorting spring-boot


【解决方案1】:

我通过 $unwind 操作解决了这个问题。

 private Aggregation makeQuery(String userId) {
        return newAggregation(
            match(Criteria.where("user_id").is(userId)),
            unwind("$meta_data.access_times"),
            group(Fields.fields().and("first_name", "$meta_data.user_data.first_name").and("last_name", "$meta_data.user_data.last_name").and("profile_pic", "$meta_data.user_data.profile_pic").and("user_id", "$user_id")).max("$meta_data.access_times").as("access_time"),
            sort(Sort.Direction.DESC, "access_time")
        );
    }

【讨论】:

    【解决方案2】:

    当您不知道要推送的元素是否已排序时(例如,正在向他推送分数的用户...)您可以按顺序使用 $push 和 $sort有一个有序的数组,那么你可以按“find({userId:yourUseId}.sort("metadata.access_time.0":-1).

    此解决方案假设您的数组在创建/更新时使用 $sort 排序:LINK

    当您确定 Push 不需要排序时(例如,您正在为该用户推送 Access_Date)您可以使用 $operator (tnx Erdenezul )。 LINK

    理论上,如果 find() 仅获取少量文档,则您不需要数组“access_time”上的索引。否则,您可以使用 {"metadata.access_time.0": -1} 添加索引。

    祝你好运!

    【讨论】:

    • 将最新访问添加到推送位置为 0 的第 0 个元素会很好
    • @Erdenezul 你认为这不是一个可行的解决方案吗?
    • 为了避免排序,在索引0处推送最新元素更有效。
    • @Erdenezul 哦,你是对的,可以使用 $position 但我刚刚发布了一个适用于任何场景的通用解决方案。
    • 你能用我的想法修改你的答案,然后我可以投票给你的答案
    猜你喜欢
    • 2020-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-25
    • 2022-12-18
    • 1970-01-01
    相关资源
    最近更新 更多