Mongo how to exclude nested _id in the nested array - mongodb

I want to exclude nested default _id in every element of array in the founded result.
I have next request. In some fields _id property can be absent.
How can I exclude it in the filters ?
Is it possible?
db.getCollection('Test').find({"name":"t1"},{"_id":0})
I get next data from DB
{
"array" : [
{
"_id": ObjectId("5685ea32ba5298688d27cceb"),
"id" : 1,
"name" : "aaa"
},
{
"_id": ObjectId("5685ea32ba5298688d27cceb"),
"id" : 2,
"name" : "bbb"
},
{
"id" : 3,
"name" : "bbb"
},
]
}
I want to get next array without _id
{
"array" : [
{
"id" : 1,
"name" : "aaa"
},
{
"id" : 2,
"name" : "bbb"
},
]
}
When I try to use
db.getCollection('Test').find({"name":"t1"},{"_id":0, "array._id":0})
I get the error like:
"errmsg" : "Projection cannot have a mix of inclusion and exclusion.",
I think the reason that some objects of array don't contain the _id property

The _id is inside an array field, so you have to use array._id,
db.getCollection('Test').find(
{ "name": "t1" },
{ "array._id": 0 }
)
Playground,
Mongo Shell

Related

How can I insert value in array inside object field in mongodb?

How can I insert an value in "total" array where pid = "123"
{
"_id" : ObjectId("625bc1983016ed5208bbdf90"),
"NAME" : "XYZ",
"data" : [
{
"pid" : "123",
"total" : [ ]
},
{
"pid" : "456",
"total" : [ ]
}
]
}
The right way is:
db.collection.update({
data: {
$elemMatch: {
pid: "123"
}
}
},
{
$set: {
"data.$.buyers": "some name"
}
})
$elemMatch allows you to match more than one component within the same array element and then you can use $set to update the specific element.
You can run it here to check the same query https://mongoplayground.net/p/lveZw-8wkZ0
You can also have a look at documentation of $elemMatch in this link.
Let me know if you face any issue.

How to count the number of documents in which an element of an object inside an array exists in a collection of Mongodb

I have a MongoDB collection called Cards containing structurally similar documents as illustrated below:
{
"_id" : ObjectId("mongoid"),
"userName": "Har109",
"array1" : [
{
"id" : "11",
"name" : "hello world",
}
{
"id" : "21",
"name" : "bye world",
}
],
"array2" : [
{
"id" : "1",
"name" : "titanic",
}
{
"id" : "2",
"name" : "avatar",
}
],
"array3" : [
{
"id" : "1",
"name" : "The Alchemist",
}
{
"id" : "2",
"name" : "What is Zero",
}
]
}
I need to query: Count the number of Documents in the collection that matches "array1.id", which I then can do it for all other arrays (e.g. "array2.id", "array3.id")
What is the syntax for this kind of query in MongoDB Compass?
I tried: the pipeline to get all the documents where there is array1
[{$count: 'array1'}]
But how do I add the condition of where array1.id = "11" to this pipeline on mongodb compass, where stages are done separately.
Count the number of Documents in the collection that matches "array1.id"
To find how many documents contain array.id=x you can run:
db.collection.find({ "array1.id":"11" }).countDocuments()
Or using aggregation
db.collection.aggregate([
{ $match:{"array1.id":"11"} },
{ count:"array1" }
])
The algorithm traverses arrays automatically.
It won't find a document if the key does not exist.

Getting array of object with limit and offset doesn't work using mongodb

First let me say that I am new to mongodb. I am trying to get the data from the collection
Here is the document in my collection student:
{
"_id" : ObjectId("5979e0473f00003717a9bd62"),
"id" : "l_7c0e37b9-132e-4054-adbf-649dbc29f43d",
"name" : "Raj",
"class" : "10th",
"assignments" : [
{
"id" : "v_539f65c2-9f45-4d92-b05e-973cf08cc571",
"name" : "1"
},
{
"id" : "v_539f65c2-9f45-4d92-b05e-973cf08cc572",
"name" : "2"
},
{
"id" : "v_539f65c2-9f45-4d92-b05e-973cf08cc573",
"name" : "3"
},
{
"id" : "v_539f65c2-9f45-4d92-b05e-973cf08cc574",
"name" : "4"
},
{
"id" : "v_539f65c2-9f45-4d92-b05e-973cf08cc575",
"name" : "5"
},
{
"id" : "v_539f65c2-9f45-4d92-b05e-973cf08cc576",
"name" : "6"
}
]
}
the output which i require is
{
"assignments" : [
{
"id" : "v_539f65c2-9f45-4d92-b05e-973cf08cc571",
"name" : "1"
},
{
"id" : "v_539f65c2-9f45-4d92-b05e-973cf08cc572",
"name" : "2"
},
{
"id" : "v_539f65c2-9f45-4d92-b05e-973cf08cc573",
"name" : "3"
},
{
"id" : "v_539f65c2-9f45-4d92-b05e-973cf08cc574",
"name" : "4"
},
{
"id" : "v_539f65c2-9f45-4d92-b05e-973cf08cc575",
"name" : "5"
},
{
"id" : "v_539f65c2-9f45-4d92-b05e-973cf08cc576",
"name" : "6"
}
]
}
for this response i used the following query
db.getCollection('student').find({},{"assignments":1})
Now what exactly I am trying is to apply limit and offset for the comments list I tried with $slice:[0,3] but it gives me whole document with sliced result
but not assignments alone so how can I combine these two in order to get only assignments with limit and offset.
You'll need to aggregate rather than find because aggregate allows you to project+slice.
Given the document from your question, the following command ...
db.getCollection('student').aggregate([
// project on assignments and apply a slice to the projection
{$project: {assignments: {$slice: ['$assignments', 2, 5]}}}
])
... returns:
{
"_id" : ObjectId("5979e0473f00003717a9bd62"),
"assignments" : [
{
"id" : "v_539f65c2-9f45-4d92-b05e-973cf08cc573",
"name" : "3"
},
{
"id" : "v_539f65c2-9f45-4d92-b05e-973cf08cc574",
"name" : "4"
},
{
"id" : "v_539f65c2-9f45-4d92-b05e-973cf08cc575",
"name" : "5"
},
{
"id" : "v_539f65c2-9f45-4d92-b05e-973cf08cc576",
"name" : "6"
}
]
}
This represents the assignments array (and only the assignments array) with a slice from element 2 to 5. You can change the slice arguments (2, 5 in the above example) to apply your own offset and limit (where the first argument is the offset and the limit is the difference between the first and second arguments).
If you want to add a match condition (to address specific documents) to the above then you'd do something like this:
db.getCollection('other').aggregate([
/// match a specific document
{$match: {"_id": ObjectId("5979e0473f00003717a9bd62")}},
// project on assignments and apply a slice to the projection
{$project: {assignments: {$slice: ['$assignments', 2, 5]}}}
])
More details on the match step here.

Reference multiple fields with aggregation function

Let's say I have some mongo DB query which returns following two documents. (I am using aggregation & projection which returns me this result set).
{
"name" : {
"value" : "ANDERSON"
},
"ID" : {
"value" : "2356"
},
}
{
"employeename" : {
"value" : "DAVID"
},
"ID" : {
"value" : "2356"
},
}
My DB is schema less & I am storing attributes and there values. There are multiple attributes which represents the same information. For e.g. here "name" & "employeename" represents the same thing. I want the final output in some common attribute (say "Employee Name"). This common attribute can have value either from "name" or "employeename".
I think this problem can be solved by adding one more pipe in with the aggregation. I tried $or (it returns true/false not the value)
db.getCollection('mycollection').aggregate([
{ "$project" : {
"name" : 1,
"ID" : 1, "employeename" : 1
}},
{ "$project":{
"Employee Name": {$or : ["$name", "$employeename"]}
}}
])
Final Output should be
{
" Employee Name" : {
"value" : "ANDERSON"
},
"ID" : {
"value" : "2356"
},
}
{
" Employee Name" : {
"value" : "DAVID"
},
"ID" : {
"value" : "2356"
},
}
Can somebody tell me how to write this mongo DB command?
What you want is the $ifNull operator, you can also shorten your pipeline to one $project stage.
db.getCollection('mycollection').aggregate([
{ "$project" : {
"EmployeeName" : { "$ifNull": [ "$name", "$employeename" ] },
"ID" : 1,
}}
])

Mongo: how to retrieve ONLY subdocs that match certain properties

Having, for example, a collection named test and the following document is inside:
{
"_id" : ObjectId("5692ac4562c824cc5167379f"),
"list" : [
{
"name" : "elem1",
"type" : 1
},
{
"name" : "elem2",
"type" : 2
},
{
"name" : "elem3",
"type" : 1
},
{
"name" : "elem4",
"type" : 3
},
{
"name" : "elem4",
"type" : 2
}
]
}
Let's say I would like to retrieve a list of only those subdocuments inside list that match:
type = 2.
I've tried the following query:
db.getCollection('test').find({
'_id': ObjectId("5692ac4562c824cc5167379f"),
'list.type': 1
})
But the result I get contains every subdocument inside list, and I guess this is because inside list there are at least one document which's type equals 1.
Instead of that, the result I am interested to obtain would be every subdocument inside list that matches 'list.type': 1:
{
"_id" : ObjectId("5692ac4562c824cc5167379f"),
"list" : [
{
"name" : "elem1",
"type" : 1
},
{
"name" : "elem3",
"type" : 1
}
]
}
...so $and $elemMatch is not what I am really looking for as they return just the first matching element.
Anyone knows how to achieve what I am looking for?
db.myCol.aggregate([
{ $unwind: "$list" },
{ $match: { "list.type":1 } },
{ $group: { "_id":"$_id", list: {$push:"$list"}} }
])