Reputation: 349
I have a collection "MyCollection" where each document could have 0,1 or many properties named "propertyX" where X is the nth time the property appears in the document.
For example, my collection could looks like this :
{
"_id":ObjectId("XXXX")
"property1":xxxxxx
"property2":xxxxxx
"property3":xxxxxx
}
{
"_id":ObjectId("XXXX")
"property1":xxxxxx
"property2":xxxxxx
"property3":xxxxxx
"property4":xxxxxx
"property5":xxxxxx
}
{
"_id":ObjectId("XXXX")
"property1":xxxxxx
"property2":xxxxxx
"property3":xxxxxx
"property4":xxxxxx
"property5":xxxxxx
"property6":xxxxxx
"property7":xxxxxx
}
I'm trying to sort documents with a mongo query by the number of propertyX they had, so in my example, the third object must be at the top of my result (7 properties), then the second one (5 properties), then the first one (only 3 properties). What I've done for the moment, is implementing it in javascript (using mongo driver) and do a count of keys with the Object.Keys(myObject).filter(key=>key.startsWith('property')) but this is taking way too much time. Is there a way to do it directly with a mongo query, thanks
Upvotes: 1
Views: 787
Reputation: 201
You can achieve this by using the aggregation tool.
First create a new property with the number of properties in you document, so you can use it to sort on a later stage:
db.getCollection("MyCollection").aggregate([
{
$addFields: {
properties: { $objectToArray: '$$ROOT' },
}
}
]);
At this stage your documents on the pipeline would look something like this:
{
"_id":ObjectId("XXXX")
"property1":xxxxxx
"property2":xxxxxx
"property3":xxxxxx
"properties: [
{ k: "_id", v: ObjectId("XXXX")},
{ k: "property1", v: xxxxxx },
{ k: "property2", v: xxxxxx },
{ k: "property3", v: xxxxxx },
]
}
Using the $size
operator you can get the length of this array:
...
{
$addFields: {
properties: { $size: { $objectToArray: '$$ROOT' }},
}
}
...
So now you would have a property that shows the number of keys in your document:
{
"_id":ObjectId("XXXX"),
"property1":xxxxxx,
"property2":xxxxxx,
"property3":xxxxxx,
"properties: 4,
}
Which would make it possible to sort the documents by properties number:
...
{
$addFields: {
properties: { $size: { $objectToArray: '$$ROOT' }},
}
},
{
$sort: { properties: -1 }
}
...
To finish you can get rid of the property properties with $unset
:
...
{
$addFields: {
properties: { $size: { $objectToArray: '$$ROOT' }},
}
},
{
$sort: { properties: -1 }
},
{
$unset: 'properties'
},
You would end up with the following:
[
{
"_id":ObjectId("XXXX"),
"property1":xxxxxx,
"property2":xxxxxx,
"property3":xxxxxx,
"property4":xxxxxx,
"property5":xxxxxx,
"property6":xxxxxx,
"property7":xxxxxx,
},
{
"_id":ObjectId("XXXX"),
"property1":xxxxxx,
"property2":xxxxxx,
"property3":xxxxxx,
"property4":xxxxxx,
"property5":xxxxxx,
},
{
"_id":ObjectId("XXXX"),
"property1":xxxxxx,
"property2":xxxxxx,
"property3":xxxxxx,
}
]
Upvotes: 1