排序数组和对象数组 MongoDb

sort array and Array of Object MongoDb

我在 MongoDB

中有一个用于理解排序的简单集合

我的文件是:

{
    "_id" : ObjectId("54b94985d74d670613e4fd35"),
    "tag" : [ 
        "A", 
        "B", 
        "Z"
    ]
}

{
    "_id" : ObjectId("54b949c9d74d670613e4fd36"),
    "tag" : [ 
        "D", 
        "E", 
        "F"
    ]
}

{
    "_id" : ObjectId("54b949dfd74d670613e4fd37"),
    "tag" : [ 
        "G", 
        "H", 
        "I"
    ]
}

当我按标签排序时,我得到了这些结果

db.candy.find().sort({tag:1})


{
    "_id" : ObjectId("54b94985d74d670613e4fd35"),
    "tag" : [ 
        "A", 
        "B", 
        "Z"
    ]
}

{
    "_id" : ObjectId("54b949c9d74d670613e4fd36"),
    "tag" : [ 
        "D", 
        "E", 
        "F"
    ]
}

{
    "_id" : ObjectId("54b949dfd74d670613e4fd37"),
    "tag" : [ 
        "G", 
        "H", 
        "I"
    ]
}

改为标签:-1

db.candy.find().sort({tag:-1})

{
    "_id" : ObjectId("54b94985d74d670613e4fd35"),
    "tag" : [ 
        "A", 
        "B", 
        "Z"
    ]
}

{
    "_id" : ObjectId("54b949dfd74d670613e4fd37"),
    "tag" : [ 
        "G", 
        "H", 
        "I"
    ]
}

{
    "_id" : ObjectId("54b949c9d74d670613e4fd36"),
    "tag" : [ 
        "D", 
        "E", 
        "F"
    ]
}

结果很相似,第一个对象是一样的,只改变了第二个和第三个。 与对象数组相同的结果。 我的问题是: 它是如何工作的? 我知道字母 A 是 Alphabetic ( ASCII CODE ) 的第一个字母,而 Z 是最后一个。 mongo 检查数组的每个元素(或对象)? 为什么当我使用 tag:-1 和 tag:1 时数组内的顺序相同?我期待

tag:1

{
    "_id" : ObjectId("54b94985d74d670613e4fd35"),
    "tag" : [ 
        "A", 
        "B", 
        "Z"
    ]
}

和标签:-1

{
    "_id" : ObjectId("54b94985d74d670613e4fd35"),
    "tag" : [ 
        "Z", 
        "A", 
        "B"
    ]
}

按数组字段对文档进行排序时的排序运算符执行以下操作:

  1. 降序时,从每个数组中取最大的元素与其他元素进行比较

  2. 升序排序时,取每个数组中最小的元素与其他元素进行比较

这些仅用于对文档进行排序,因此文档中的顺序是相同的

With arrays, a less-than comparison or an ascending sort compares the smallest element of arrays, and a greater-than comparison or a descending sort compares the largest element of the arrays. As such, when comparing a field whose value is a single-element array (e.g. [ 1 ]) with non-array fields (e.g. 2), the comparison is between 1 and 2. A comparison of an empty array (e.g. [ ]) treats the empty array as less than null or a missing field.

http://docs.mongodb.org/manual/reference/method/cursor.sort/

只是重复和详细说明@marcinn,回答。

发出以下语句时,它要求 mongodbsort 传递给 find() 语句的查询找到的文档,在这种情况下,所有文档在集合中将由 find() 函数返回,由 tag 字段返回。

这里要注意的一点是,字段 tag 是类型 array 而不是 simple 字段。

db.candy.find().sort({tag:1})

如果它是一个简单的字段,文档将按 tag 字段中的值排序。

无论如何,mongodb 需要一个可以对文档进行排序的值。要获取字段的值,mongodb 执行以下操作:

  • 检查 tag 是否为数组。如果是数组,则需要选择一个 数组中的元素,其值可以假定为的权重 特定文档。
  • 现在它检查指定的排序是升序还是降序 订单。
  • 如果是升序,就找tag中最小的元素 数组,否则最大。
  • 使用从标签数组中选择的元素,对于每个文档, 已应用排序。

这里需要注意的一个重点是,排序操作只是改变了检索到的root个文档的顺序,换句话说,它就像一个order by SQL 条款中的子句。

不会更改每个文档的标签数组元素的顺序。

根据经验,find() 查询(链接到 limitsort 操作)不会更改检索到的文档的结构。要操纵文档的结构,您需要执行聚合操作。

您在问题中所期望的是通过操作每个文档中的字段来实现的,只有聚合操作才能做到这一点。

因此,如果您将其汇总为,

db.candy.aggregate([
{$match:{"_id":ObjectId("54b94985d74d670613e4fd35")}},
{$unwind:"$tag"},
{$sort:{"tag":-1}},
{$group:{"_id":"$_id","tag":{$push:"$tag"}}}
])

那么您可以得到如下结果:

{
    "_id" : ObjectId("54b94985d74d670613e4fd35"),
    "tag" : [ 
        "Z", 
        "A", 
        "B"
    ]
}