I have data saved in the following:
{
"_id" : ObjectId("57723b5e009793e8f3cfd1d7"),
"room" : "1003",
"inout" : {
"1" : [
"i1654",
"o1656",
"i1706",
"o1707",
],
"2" : [
"i1655",
"o1656",
"i1715",
"o1715"
],
"3" : [
"i1801"
]
}
}
how to count and paginate the subdocument "inout" which is an object?
thanks!!!
Actually, there is a small modification required in your JSON. The "inout" should be an array to use the below solution.
"$unwind" can be used here.
Modified JSON to define "inout" as array rather than Object:-
db.rooms_second.insertOne({
"_id" : ObjectId("57723b5e009793e8f3cfd1d7"),
"room" : "1003",
"inout" : [
{"1" : [
"i1654",
"o1656",
"i1706",
"o1707",
]},
{"2" : [
"i1655",
"o1656",
"i1715",
"o1715"
]},
{"3" : [
"i1801"
]}
]
});
Mongodb Query:-
In the resultset, the below query will give you one record for each element in the "inout" array.
db.rooms_second.aggregate([ { $unwind: "$inout" } ])
The pagination can be done based on the driver and API that you are using (i.e. MongoDB Java Driver etc.).
Related
i need to create a mongodb query to convert an array into key-value
my document is like this:
{
"_id" : ObjectId("5c8718b9b5fe262104408374"),
"axis" : "x",
"message_time" : ISODate("2019-03-11T08:04:41.000Z"),
"x_axis" : [
0.9766,
1.9531,
2.9297,
3.9063,
4.8828,
5.8594,
6.8359,
7.8125,
8.7891,
],
"etl_date_time" : ISODate("2019-03-12T02:26:01.510Z")
}
i want to convert it to
{
"_id" : ObjectId("5c8718b9b5fe262104408374"),
"axis" : "x",
"message_time" : ISODate("2019-03-11T08:04:41.000Z"),
"x_axis" : 8.7891,
"etl_date_time" : ISODate("2019-03-12T02:26:01.510Z")
}
can anyone help me with the query?
You can use aggreggation framework to achieve this.
db.collection.aggregate([
{
$addFields: {
x_axis: {
$arrayElemAt: [
{
$slice: [
"$x_axis",
-1
]
},
0
]
}
}
}
])
If you need to perform an update on your collection, you can add an $out stage
Mongo playground
I'm quite new to mongodb and there is one thing I can't solve right now:
Let's pretend, you have the following document structure:
{
"_id": ObjectId("some object id"),
name: "valueName",
options: [
{idOption: "optionId", name: "optionName"},
{idOption: "optionId", name: "optionName"}
]
}
And each document can have multiples options that are already classified.
I'm trying to get all the documents in the collection that have, at least one, of the multiples options that I pass for the query.
I was trying with the operator $elemMatch something like this:
db.collectioName.find({"options.name": { $elemMatch: {"optName1","optName2"}}})
but it never show me the matches documents.
Can someone help and show me, what I'm doing wrong?
Thanks!
Given a collection which contains the following documents:
{
"_id" : ObjectId("5a023b8d027b5bd06add627a"),
"name" : "valueName",
"options" : [
{
"idOption" : "optionId",
"name" : "optName1"
},
{
"idOption" : "optionId",
"name" : "optName2"
}
]
}
{
"_id" : ObjectId("5a023b9e027b5bd06add627d"),
"name" : "valueName",
"options" : [
{
"idOption" : "optionId",
"name" : "optName3"
},
{
"idOption" : "optionId",
"name" : "optName4"
}
]
}
This query ...
db.collection.find({"options": { $elemMatch: {"name": {"$in": ["optName1"]}}}})
.. will return the first document only.
While, this query ...
db.collection.find({"options": { $elemMatch: {"name": {"$in": ["optName1", "optName3"]}}}})
...will return both documents.
The second example (I think) meeets this requirement:
I'm trying to get all the documents in the collection that have, at least one, of the multiples options that I pass for the query.
My mongo db collection contains the structure as :
{
"_id" : ObjectId("5889ce0d2e9bfa938c49208d"),
"filewise_word_freq" : {
"33236365" : [
[
"cluster",
4
],
[
"question",
2
],
[
"differ",
2
],[
"come",
1
]
],
"33204685" : [
[
"node",
6
],
[
"space",
4
],
[
"would",
3
],[
"templat",
1
]
]
},
"file_root" : "socialcast",
"main_cluster_name" : "node",
"most_common_words" : [
[
"node",
16
],
[
"cluster",
7
],
[
"n't",
3
]
]
}
I want to search for a value "node" inside the arrays of arrays of the filename (in my case its "33236365","33204685" and so on...) of the dict filewise_word_freq.
And if the value("node") is present inside any one of the array of arrays of the filename(33204685), then should return the filename(33204685).
I tried from this link of stackoverflow :
enter link description here
I tried to execute for my use case it didn't work. And above all this I didn't no how to return only the filename rather the entire object or document.
db.frequencydist.find({"file_root":'socialcast',"main_cluster_name":"node","filewise_word_freq":{$elemMatch:{$elemMatch:{$elemMatch:{$in:["node"]}}}}}).pretty().
It returned nothing.
Kindly help me.
the data model you have chosen has made it extremely difficult to either query or even for aggregation. I would suggest to revise your document model. However I think you can use $where
db.collection.find({"file_root": 'socialcast',
"main_cluster_name": "node", $where : "for(var i in this.filewise_word_freq){for(var j in this.filewise_word_freq[i]){if(this.filewise_word_freq[i][j].indexOf("node")>=0){return true}}}"})
yes, this will return you the whole document and from your application you might need to filter the files name out.
you might also want to see map-reduce functionality, though that's not recommended.
One other way is to do it through functions, functions runs on mongo server and are saved in a special collection.
Still going back to the db model, do revise it if that's a possibility. maybe something like
{
"_id" : ObjectId("5889ce0d2e9bfa938c49208d"),
"filewise_word_freq" : [
{
"fileName":"33236365",
"word_counts" : {
"cluster":4,
"question":2,
"differ":2,
"come":1
}
},
{
"fileName":"33204685",
"word_counts" : {
"node":6,
"space":4,
"would":3,
"template":1
}
}
]
"file_root" : "socialcast",
"main_cluster_name" : "node",
"most_common_words" : [
{
"node":16
},
{
"cluster":7
},
{
"n't":3
}
]
}
It would be a lot easier to run aggregation on these.
For this model, the aggregation would be something like
db.collection.aggregate([
{$unwind : "$filewise_word_freq"},
{$match : {'filewise_word_freq.word_counts.node' : {$gte : 0}}},
{$group :{_id: 1, fileNames : {$addToSet : "$filewise_word_freq.fileName"}}},
{$project :{ _id:0}}
])
this will provide you a single document with a single field fileNames with list of all the filename
{
fileNames : ["33204685"]
}
You can try something like this. This will match the node as part of the query and returns filewise_word_freq.33204685 as part of the projection.
db.collection.find({
"file_root": 'socialcast',
"main_cluster_name": "node",
"filewise_word_freq.33204685": {
$elemMatch: {
$elemMatch: {
$in: ["node"]
}
}
}
}, {
"filewise_word_freq.33204685": 1
}).pretty();
I have a collection that stored information about devices like the following:
/* 1 */
{
"_id" : {
"startDate" : "2012-12-20",
"endDate" : "2012-12-30",
"dimensions" : ["manufacturer", "model"],
"metrics" : ["deviceCount"]
},
"data" : {
"results" : "1"
}
}
/* 2 */
{
"_id" : {
"startDate" : "2012-12-20",
"endDate" : "2012-12-30",
"dimensions" : ["manufacturer", "model"],
"metrics" : ["deviceCount", "noOfUsers"]
},
"data" : {
"results" : "2"
}
}
/* 3 */
{
"_id" : {
"dimensions" : ["manufacturer", "model"],
"metrics" : ["deviceCount", "noOfUsers"]
},
"data" : {
"results" : "3"
}
}
And I am trying to query the documents using the _id field which will be unique. The problem I am having is that when I query for all the different attributes as in:
db.collection.find({$and: [{"_id.dimensions":{ $all: ["manufacturer","model"], $size: 2}}, {"_id.metrics": { $all:["noOfUsers","deviceCount"], $size: 2}}]});
This matches 2 and 3 documents (I don't care about the order of the attributes values), but I would like to only get 3 back. How can I say that there should not be any other attributes to _id than those that I specify in the search query?
Please advise. Thanks.
Unfortunately, I think the closest you can get to narrowing your query results to just unordered _id.dimensions and unordered _id.metrics requires you to know the other possible fields in the _id subdocument field, eg. startDate and endDate.
db.collection.find({$and: [
{"_id.dimensions":{ $all: ["manufacturer","model"], $size: 2}},
{"_id.metrics": { $all:["noOfUsers","deviceCount"], $size: 2}},
{"_id.startDate":{$exists:false}},
{"_id.endDate":{$exists:false}}
]});
If you don't know the set of possible fields in _id, then the other possible solution would be to specify the exact _id that you want, eg.
db.collection.find({"_id" : {
"dimensions" : ["manufacturer", "model"],
"metrics" : ["deviceCount", "noOfUsers"]
}})
but this means that the order of _id.dimensions and _id.metrics is significant. This last query does a document match on exact BSON representation of _id.
Theres something here I can't quite figure out.
When I attempt to query an object with several fields I yield no results. The object structure looks like this:
{
"_id" : ObjectId("4d8b55f017a7303b0b000000"),
"title" : "Apollo",
"body" : "A spaceflight mission to the moon",
"tags" : [ [ "moon", "space", "nasa", "mission" ] ]
}
This is my query:
db.test.find({ tags: { $all: ['moon', 'mission'] } })
However I do get result by creating a new object with a single field:
{
"_id" : ObjectId("4d8b9e5935037b3c8228709c"),
"tags" : [ "apple", "banana", "pear" ]
}
... with the same query as the one above.
['tags'] isn't nested inside any other array, so why does it not return my search queries? Please enlighten me.
Sincerely,
Why
Why are you using a nested array
"tags" : [ [ "moon", "space", "nasa", "mission" ] ]
here?
This does not make any sense.
db.test.find({ tags: { $all: [ ['moon', 'mission'] ] } })