Reputation: 4671
I have a simple Collection for understand sort in MongoDB
my documents are:
{
"_id" : ObjectId("54b94985d74d670613e4fd35"),
"tag" : [
"A",
"B",
"Z"
]
}
{
"_id" : ObjectId("54b949c9d74d670613e4fd36"),
"tag" : [
"D",
"E",
"F"
]
}
{
"_id" : ObjectId("54b949dfd74d670613e4fd37"),
"tag" : [
"G",
"H",
"I"
]
}
When I sort by Tag I Have these results
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"
]
}
Instead with tag:-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"
]
}
The results are very similar, the first object It's the same and Change only the second and the third. Same Results with Array of object. My question is: How it works the sort? I know that the letter A is the first letter of Alphabetic ( ASCII CODE ) and the Z is the last. The mongo check each element ( or object ) of array ? And Why the order inside array is the same when I use tag:-1 and tag:1 ? I expect something like
tag:1
{
"_id" : ObjectId("54b94985d74d670613e4fd35"),
"tag" : [
"A",
"B",
"Z"
]
}
And tag:-1
{
"_id" : ObjectId("54b94985d74d670613e4fd35"),
"tag" : [
"Z",
"A",
"B"
]
}
Upvotes: 0
Views: 3684
Reputation: 19700
Just to re-iterate and elaborate on @marcinn, answer.
When the below statement is issued, it asks mongodb
to sort
the documents that were found by the query passed to the find()
statement, in this case, all the documents in the collection would be returned by the find()
function, by the tag
field.
A point to note here is, the field tag
is of type array
and not a simple field.
db.candy.find().sort({tag:1})
If it were a simple field, the documents would have been sorted by the value in the tag
field.
Anyway, mongodb needs a value by which it can sort the documents. To get the value of the field, mongodb does the following:
tag
is an array. If it is an array, it needs to choose an
element from the array whose value it can assume to be the weight of
particular document.One important point to note here is that, the sort operation only changes the order of the root documents retrieved, in other words, it acts like an order by
clause in SQL
terms.
It does not change the order of the tag array elements for each document.
As a rule of thumb, a find()
query, with limit
, sort
operations chained to it, does not change the structure of the retrieved documents. To manipulate the structure of the documents you need to perform an aggregate operation.
What you expect in your question, is achieved by manipulating the fields in each document, which only an aggregation operation can do.
So if you aggregate it as,
db.candy.aggregate([
{$match:{"_id":ObjectId("54b94985d74d670613e4fd35")}},
{$unwind:"$tag"},
{$sort:{"tag":-1}},
{$group:{"_id":"$_id","tag":{$push:"$tag"}}}
])
then you could get your result as:
{
"_id" : ObjectId("54b94985d74d670613e4fd35"),
"tag" : [
"Z",
"A",
"B"
]
}
Upvotes: 3
Reputation: 1786
sort operator when sorting docs by array field, does the following:
When sorting descending, it takes the biggest element from each array and compares with other
When sorting ascending , it takes the smallest element from each array and compares with other
These are used only to sort the documents, so thats why the order inside the document is the same
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/
Upvotes: 4