i want to know how many elements there are inside objects.
My collections is the following:
{"_id": 'xxx',
"ments":{
"_id_ab6666djdkjd": {
"text": "my text"
},
"_id_ab6dee": {
"text": "my text2"
}
}
},
{"_id": 'xxx',
"ments":{
"_id_ab6666dddjdkjd": {
"text": "my text"
}
}
}
I want to count ments in all documents? I know that is best practise use array in ments but i can't change the schema design.
Best, Lorenzo
i want to know how many elements there are inside objects.
My collections is the following:
{"_id": 'xxx',
"ments":{
"_id_ab6666djdkjd": {
"text": "my text"
},
"_id_ab6dee": {
"text": "my text2"
}
}
},
{"_id": 'xxx',
"ments":{
"_id_ab6666dddjdkjd": {
"text": "my text"
}
}
}
I want to count ments in all documents? I know that is best practise use array in ments but i can't change the schema design.
Best, Lorenzo
Share Improve this question edited Jun 30, 2017 at 8:21 Neil Lunn 151k36 gold badges355 silver badges325 bronze badges asked Mar 12, 2015 at 14:51 JBerta93JBerta93 7193 gold badges16 silver badges28 bronze badges 1- 3 You'll have to retrieve the document and count the subobject's keys in the client. It's probably not a useful schema, so it's unfortunate if you can't change it. – wdberkeley Commented Mar 12, 2015 at 18:31
1 Answer
Reset to default 9Go you your boss and tell them I told them to "Change the Design". Here's the post you should them with me telling them.
The design is horrible and you cannot work on it without processing with code, either on the client or server. On the server that means JavaScript interpretation, in which both the required processing and lack of being able to use better in-build features of MongoDB.
Ideally you should have documents that look like this:
{
"ments":[
{ "_id": "ab6666djdkjd", "text": "my text" }
{ "_id": "ab6dee", "text": "my text2" }
],
"mentCount": 2
},
{
"ments":{
{ "_id": "ab6666dddjdkjd", "text": "my text" }
],
"mentCount": 1
}
So not only structured as an array but also keeping the "length" of the array, which is easy to do using the $inc
operator along with $push
and $pull
operations.
Your most simple query then bees this:
db.collection.aggregate([
{ "$group": {
"_id": null,
"count": { "$sum": "$mentCount" }
}}
])
So without a structure to support it you are stuck with running a much slower processor with mapReduce:
db.collection.mapReduce(
function() {
emit( null, Object.keys(this.ments).length );
},
function(key,values) {
return Array.sum(values);
},
{
"out": { "inline": 1 }
}
)
That will sum all the ments in all documents in the collection on your existing structure.
The two things to consider is you are essentially placing "data" within the values of "keys" in this design and creating document paths that are notoriously difficult to "query". When data is present in the key it cannot be indexed, which is going to lead to poor performance as your application usage grows.
The other consideration is that you need "code" to process most of your inquiry needs either client or server side, and in most cases standard query operators or aggregation built-in's will do this much better.
So you can use code as has been shown but really make the change now, because you are going to have to sooner or later as everything in the application slows down.