简体   繁体   English

按特定内容然后按时间戳对 MongoDB 文档进行排序

[英]Sort MongoDB documents by specific content then by timestamp

I'm using nodejs with official mongodb's package.我正在使用带有官方 mongodb 包的 nodejs。 I got many documents in mongodb containing "type" and "timestamp" field.我在 mongodb 中得到了许多包含“type”和“timestamp”字段的文档。 I want to sort it by prioritizing "type" (only specific content) and then "timestamp".我想通过优先“类型”(仅限特定内容)然后“时间戳”来对其进行排序。 As example I have following documents:例如,我有以下文件:

{ type: "book", timestamp: 1580825471 }
{ type: "house", timestamp: 1580825502 }
{ type: "water", timestamp: 1580825515 }
{ type: "book", timestamp: 1580825478 }
{ type: "smartphone", timestamp: 1580825522 }
{ type: "book", timestamp: 1580825424 }

My goal is to have sorted by that way to priority the type "book" first (and then sort it by timestamp)我的目标是按这种方式排序,首先优先考虑“书”类型(然后按时间戳排序)

{ type: "book", timestamp: 1580825478 }
{ type: "book", timestamp: 1580825471 }
{ type: "book", timestamp: 1580825424 }
{ type: "smartphone", timestamp: 1580825522 }
{ type: "water", timestamp: 1580825515 }
{ type: "house", timestamp: 1580825502 }

I was trying to use the db.collection.aggregate with following $sort value:我试图使用具有以下 $sort 值的 db.collection.aggregate:

$sort: {
    type: "book",
    timestamp: -1
}

But that didn't worked out because the $sort field's value can only have the value of " 1 ", " -1 " or " { $meta: "textScore" } ".但这并没有奏效,因为 $sort 字段的值只能具有“ 1 ”、“- 1 ”或“ {$meta:“textScore”} ”的值。

Does anybody have an idea how to solve that issue?有没有人知道如何解决这个问题?

Thanks in advance提前致谢

EDIT:编辑:

This solution by using此解决方案使用

$sort: {
  type: 1,
  timestamp: -1
}

is not a solution since then all types are also sorted which I don't want it.不是一个解决方案,因为所有类型也被排序,我不想要它。 I just want to have "book" as first result then after that, types can be randomized (but timestamp is still being sorted.).我只想将“书”作为第一个结果,然后,类型可以随机化(但时间戳仍在排序。)。 Reason for that is that I want to list history entries (that's why I'm using timestamp to sort it), but I want to show type "book" at first.原因是我想列出历史条目(这就是我使用时间戳对其进行排序的原因),但我想首先显示类型“书”。 Even if the document are older than other documents.即使该文档比其他文档旧。 So yeah, for other types expect "book", I want it to be sorted by timestamp.所以是的,对于其他类型的“书”,我希望它按时间戳排序。

You can add an extra field in a project stage that creates a sort priority, then use that to sort on.您可以在项目阶段添加一个额外的字段来创建排序优先级,然后使用它进行排序。

For example:例如:

db.data.aggregate([
    { $addFields : { sortPriority: { $eq: [ "$type", "book" ] } } },
    { $sort: { sortPriority: -1, timestamp: -1} }
])

This will output the following:这将输出以下内容:

{ "_id" : ObjectId("5e39892e0f18de54afe4d874"), "type" : "book", "timestamp" : 1580825478, "sortPriority" : true }
{ "_id" : ObjectId("5e39892e0f18de54afe4d871"), "type" : "book", "timestamp" : 1580825471, "sortPriority" : true }
{ "_id" : ObjectId("5e39892e0f18de54afe4d876"), "type" : "book", "timestamp" : 1580825424, "sortPriority" : true }
{ "_id" : ObjectId("5e39892e0f18de54afe4d875"), "type" : "smartphone", "timestamp" : 1580825522, "sortPriority" : false }
{ "_id" : ObjectId("5e39892e0f18de54afe4d873"), "type" : "water", "timestamp" : 1580825515, "sortPriority" : false }
{ "_id" : ObjectId("5e39892e0f18de54afe4d872"), "type" : "house", "timestamp" : 1580825502, "sortPriority" : false }

If you want to ommit the extra field add $unset stage:如果你想省略额外的字段添加$unset阶段:

db.data.aggregate([
    { $addFields : { sortPriority: { $eq: [ "$type", "book" ] } } },
    { $sort: { sortPriority: -1, timestamp: -1} },
    { $unset: "sortPriority" }
])

This will then output:这将输出:

{ "_id" : ObjectId("5e39892e0f18de54afe4d874"), "type" : "book", "timestamp" : 1580825478 }
{ "_id" : ObjectId("5e39892e0f18de54afe4d871"), "type" : "book", "timestamp" : 1580825471 }
{ "_id" : ObjectId("5e39892e0f18de54afe4d876"), "type" : "book", "timestamp" : 1580825424 }
{ "_id" : ObjectId("5e39892e0f18de54afe4d875"), "type" : "smartphone", "timestamp" : 1580825522 }
{ "_id" : ObjectId("5e39892e0f18de54afe4d873"), "type" : "water", "timestamp" : 1580825515 }
{ "_id" : ObjectId("5e39892e0f18de54afe4d872"), "type" : "house", "timestamp" : 1580825502 }

You can create a sorting key by your own:您可以自己创建排序键:

db.col.aggregate([
   {
      $addFields: {
         sortBy: {
            $cond: {
               if: { $eq: ["$type", "book"] }, then: 0, else: 1
            }
         }
      }
   },
   { $sort: { sortBy: 1, timestamp: 1 } },
   { $unset: "sortBy" }
])

Output:输出:

{ "_id" : ObjectId("5e398952227b6d209de231bb"), "type" : "book", "timestamp" : 1580825424, "sortPriority" : true }
{ "_id" : ObjectId("5e398952227b6d209de231b6"), "type" : "book", "timestamp" : 1580825471, "sortPriority" : true }
{ "_id" : ObjectId("5e398952227b6d209de231b9"), "type" : "book", "timestamp" : 1580825478, "sortPriority" : true }
{ "_id" : ObjectId("5e398952227b6d209de231b7"), "type" : "house", "timestamp" : 1580825502, "sortPriority" : false }
{ "_id" : ObjectId("5e398952227b6d209de231b8"), "type" : "water", "timestamp" : 1580825515, "sortPriority" : false }
{ "_id" : ObjectId("5e398952227b6d209de231ba"), "type" : "smartphone", "timestamp" : 1580825522, "sortPriority" : false }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM