How to query an array of _id in MongoDB? - mongodb

I have collection Collection1 and I need to fetch an array like: [id1, id2, id3, ...] (array which consist of _id`s for every element in this collection). Is there any way to do this query with MongoDB tools ? Thank you!

You will have to use cursor.toArray() function on result of find having a projection document projecting only _id i.e ObjectId() value
MongoDB Enterprise > db.users.find().pretty()
{
"_id" : ObjectId("570e1d465a44f125ef156791"),
"name" : "Ritesh Talreja",
"age" : 22,
"gender" : "M"
}
{
"_id" : ObjectId("570e1e1d5a44f125ef156792"),
"name" : "Saloni",
"age" : 21,
"gender" : "F"
}
{
"_id" : ObjectId("570e1e485a44f125ef156793"),
"name" : "abcd",
"age" : 22,
"gender" : "M"
}
{
"_id" : ObjectId("570e28d45a44f125ef156794"),
"name" : "Saloni",
"age" : 21,
"gender" : "F"
}
{ "_id" : 123 }
MongoDB Enterprise > db.users.find({}, {_id:1}).toArray()
[
{
"_id" : ObjectId("570e1d465a44f125ef156791")
},
{
"_id" : ObjectId("570e1e1d5a44f125ef156792")
},
{
"_id" : ObjectId("570e1e485a44f125ef156793")
},
{
"_id" : ObjectId("570e28d45a44f125ef156794")
},
{
"_id" : 123
}
]
MongoDB Enterprise >
As an addition you can also use:
MongoDB Enterprise > db.users.distinct("_id")
[
123,
ObjectId("570e1d465a44f125ef156791"),
ObjectId("570e1e1d5a44f125ef156792"),
ObjectId("570e1e485a44f125ef156793"),
ObjectId("570e28d45a44f125ef156794")
]
MongoDB Enterprise >

Related

Mongodb - Return all the associative documents with value for the key derived from another query

I have a document of following structure:
{
"Type" : "Request",
"Cat" : "A",
"ID" : 10
}
{
"Type" : "Processed",
"Cat" : "A",
"ID" : 10
}
{
"Type" : "Receieved",
"Cat" : "A",
"ID" : 10
}
{
"Type" : "Receieved",
"Cat" : "B",
"ID" : 11
}
{
"Type" : "Processed",
"Cat" : "C",
"ID" : 12
}
I want documents:
Those documents with Type: "Processed" and get its ID
And all the associated documents with the ID got from above (1st step).
I need the results to be like this:
{
"Type" : "Request"
"Cat" : "A"
"ID" : 10
}
{
"Type" : "Processed"
"Cat" : "A"
"ID" : 10
}
{
"Type" : "Receieved"
"Cat" : "A"
"ID" : 10
}
{
"Type" : "Processed"
"Cat" : "C"
"ID" : 12
}
Can someone help me on how to achieve this ? I used elemmatch under $match in aggregate - but its not working as expected.
You can try something like
db.collection.aggregate([
{$project : {
"ID":1,
"doc.Type" : "$Type",
"doc.Cat" : "$Cat",
"doc.ID" : "$ID"
}
}
{$group : {
_id : "$ID",
docs : {$push : doc}
}
},
{$match : {
"docs.Type":"Processed"
}
},
{$unwind : "$docs"},
{$project : {
_id : 0,
docs : 0,
"Type" : "$docs.Type",
"Cat" : "$docs.Cat",
"ID" : "$docs.ID"
}
}
])

Querying Embedded array fields in a document in mongodb

In mongodb databse, am having problem trying to query a field. My collection users looks like this:
{
"_id" : "sam",
"_password" : "t",
"data" : [
{
"_id" : "hp",
"nodeList" : [{'nodeId' : 1},{'nodeId' : 2},{'nodeId' : 3}],
"edgeList" : [{'edgeId' : 1},{'edgeId' : 2},{'edgeId' : 3}],
"options" : {
"edgeColor" : "blue",
"nodeColor" : "black"
}
},
{
"_id" : "tt",
"nodeList" : [{'nodeId' : 1},{'nodeId' : 2},{'nodeId' : 3}],
"edgeList" : [{'edgeId' : 1},{'edgeId' : 2},{'edgeId' : 3}],
"options" : {
"edgeColor" : "blue",
"nodeColor" : "black"
}
}
]},
{
"_id" : "bob",
"_password" : "w",
"data" : [
{
"_id" : "hello",
"nodeList" : [{'nodeId' : 1},{'nodeId' : 2},{'nodeId' : 3}],
"edgeList" : [{'edgeId' : 1},{'edgeId' : 2},{'edgeId' : 3}],
"options" : {
"edgeColor" : "blue",
"nodeColor" : "black"
}
},
{
"_id" : "world",
"nodeList" : [{'nodeId' : 1},{'nodeId' : 2},{'nodeId' : 3}],
"edgeList" : [{'edgeId' : 1},{'edgeId' : 2},{'edgeId' : 3}],
"options" : {
"edgeColor" : "blue",
"nodeColor" : "black"
}
}
]
}
I need to retrieve the nodeList/edgeList from this and also change the edgeColor in options given a particular _id. For eg : _ id : "bob".
I tried a few things but could not get the output.
db.users.find({ '_id': 'sam' , "users.data._id" : "hp"}, {})
db.users.findOneAndUpdate({"_id":"sam", "users.data._id": "hp"},{$addToSet:{"users.data.nodeList":{"nodeId":1,"nodeName":"Bellanduru", "lat":43.12, "long":33.43,"stock":3}}})
Please tell me what's wrong.
you declare your collection name with this db.users in selected db
and you select users collection so not necessary specify in query
for example this "users.data._id" replace with this "data._id"
replace your querys like this
db.users.find({ '_id': 'sam' , "data._id" : "hp"}, {})
db.users.findOneAndUpdate({"_id":"sam", "data._id": "hp"},{$addToSet:{"data.nodeList":{"nodeId":1,"nodeName":"Bellanduru", "lat":43.12, "long":33.43,"stock":3}}})

MongoDB - Returning only matching Array from Object

i have the following document in a collection:
{
"_id" : 101,
"students" : [
{
"name" : "john",
"age" : 10,
"city":'CA'
},
{
"name" : "danial",
"age" : 15,
"city":'KA'
}
]
}
{
"_id" : 102,
"students" : [
{
"name" : "adam",
"age" : 20,
"city":'NY'
},
{
"name" : "johnson",
"age" : 12,
"city":'CA'
}
]
}
And i fire the following query:
db.data.find({'students.city':'CA'})
This returns me "students" objects from both the documents, as one instance matches the filter ("city"; 'CA') in both.
However, i desire to only get the matching array in the result. That is, i want the following result:
{
"_id" : 101,
"students" : [
{
"name" : "john",
"age" : 10,
"city":'CA'
}
]
}
{
"_id" : 102,
"students" : [
{
"name" : "johnson",
"age" : 12,
"city":'CA'
}
]
}
Please help.
You need to use $elemMatch in your projection:
> db.data.find({'students.city':'CA'},{ students:{ $elemMatch:{'city':'CA'} }})
{ "_id" : 101, "students" : [ { "name" : "john", "age" : 10, "city" : "CA" } ] }
{ "_id" : 102, "students" : [ { "name" : "johnson", "age" : 12, "city" : "CA" } ] }
Btw: I'd strongly suggest reading the Open letter to students with homework problems.
I think you should use an aggregation operation.
Here you have the documentation:
https://docs.mongodb.org/manual/aggregation/
And a similar question:
Retrieve only the queried element in an object array in MongoDB collection

mongodb Embedded document search on parent and child field

I have a nested embedded document CompanyProduct below is structure
{
"_id" : ObjectId("53d213c5ddbb1912343a8ca3"),
"CompanyID" : 90449,
"Name" : Company1,
"CompanyDepartment" : [
{
"_id" : ObjectId("53d213c5ddbb1912343a8ca4")
"DepartmentID" : 287,
"DepartmentName" : "Stores",
"DepartmentInventory" : [
{
"_id" : ObjectId("53b7b92eecdd765430d763bd"),
"ProductID" : 1,
"ProductName" : "abc",
"Quantity" : 100
},
{
"_id" : ObjectId("53b7b92eecdd765430d763bd"),
"ProductID" : 2,
"ProductName" : "xyz",
"Quantity" : 1
}
],
}
],
}
There can be N no of companies and each company can have N number of departments and each department can have N number of products.
I want to do a search to find out a particular product quantity under a particular company
I tried below query but it does not work. It returns all the products for the specific company, the less than 20 condition doesn't work.
db.CompanyProduct.find({$and : [{"CompanyDepartment.DepartmentInventory.Quantity":{$lt :20}},{"CompanyID":90449}]})
How should the query be?
You are searching from companyProduct's sub documents. So it will return you companyProduct whole document, it is NoSQL database , some how we do not need to normalize the collection , but your case it has to be normalize , like if you want to EDIT/DELETE any sub document and if there are thousand or millions of sub document then what will you do ... You need to make other collection with the name on CompanyDepartment and companyProduct collection should be
productCompany
{
"_id" : ObjectId("53d213c5ddbb1912343a8ca3"),
"CompanyID" : 90449,
"Name" : Company1,
"CompanyDepartment" : ['53d213c5ddbb1912343a8ca4'],
}
and other collection companyDepartment
{
"_id" : ObjectId("53d213c5ddbb1912343a8ca4")
"DepartmentID" : 287,
"DepartmentName" : "Stores",
"DepartmentInventory" : [
{
"_id" : ObjectId("53b7b92eecdd765430d763bd"),
"ProductID" : 1,
"ProductName" : "abc",
"Quantity" : 100
},
{
"_id" : ObjectId("53b7b92eecdd765430d763bd"),
"ProductID" : 2,
"ProductName" : "xyz",
"Quantity" : 1
}
],
}
after this you got array of companyDeparment' ID and only push and pull query will be used on productCompany
A Solution can be
db.YourCollection.aggregate([
{
$project:{
"CompanyDepartment.DepartmentInventory":1,
"CompanyID" : 1
}
},{
$unwind: "$CompanyDepartment"
},{
$unwind: "$CompanyDepartment.DepartmentInventory"
},{
$match:{$and : [{"CompanyDepartment.DepartmentInventory.Quantity":{$lt :20}},{"CompanyID":90449}]}
}
])
the result is
{
"result" : [
{
"_id" : ObjectId("53d213c5ddbb1912343a8ca3"),
"CompanyID" : 90449,
"CompanyDepartment" : {
"DepartmentInventory" : {
"_id" : ObjectId("53b7b92eecdd765430d763bd"),
"ProductID" : 2,
"ProductName" : "xyz",
"Quantity" : 1
}
}
}
],
"ok" : 1
}

$elemMatch dosen't work after $unwind in MongoDB Aggregation Framework

I have a collection of the following data:
{
"_id" : ObjectId("51f1fcc08188d3117c6da351"),
"cust_id" : "abc123",
"ord_date" : ISODate("2012-10-03T18:30:00Z"),
"status" : "A",
"price" : 25,
"items" : [{
"sku" : "ggg",
"qty" : 7,
"price" : 2.5
}, {
"sku" : "ppp",
"qty" : 5,
"price" : 2.5
}]
}
I am using the query:
cmd { "aggregate" : "orders" , "pipeline" : [
{ "$unwind" : "$items"} ,
{ "$match" : { "items" : { "$elemMatch" : { "qty" : { "$in" : [ 7]}}}}} ,
{ "$group" : { "price" : { "$first" : "$price"} , "items" : { "$push" : { "sku" : "$items.sku"}} , "_id" : { "items" : "$items"}}} ,
{ "$sort" : { "price" : -1}} ,
{ "$project" : { "_id" : 0 , "price" : 1 , "items" : 1}}
]}
Not able to understand what is going wrong
It's because you're doing $match after $unwind. $unwind generates a new stream of documents where items is no longer an array (see docs).
It emits each document as many times as there are items in it.
If you want to select documents with desired element in it and then process all of its documents, you should call $match first:
db.orders.aggregate(
{ "$match" : { "items" : { "$elemMatch" : { "qty" : { "$in" : [ 7]}}}}},
{ "$unwind" : "$items"},
...
);
If you want to select items to be processed after $unwind, you shoul remove $elemMatch:
db.orders.aggregate(
{ "$unwind" : "$items"},
{ "$match" : { "items.qty" : { "$in" : [7]}}},
...
);
In first case you'll get two documents:
{
"price" : 25,
"items" : [
{"sku" : "ppp"}
]
},
{
"price" : 25,
"items" : [
{"sku" : "ggg"}
]
}
and in second case you'll get one:
{
"price" : 25,
"items" : [
{"sku" : "ggg"}
]
}
Update. After $unwind your documents will look like:
{
"_id" : ObjectId("51f1fcc08188d3117c6da351"),
"cust_id" : "abc123",
"ord_date" : ISODate("2012-10-03T18:30:00Z"),
"status" : "A",
"price" : 25,
"items" : {
"sku" : "ggg",
"qty" : 7,
"price" : 2.5
}
}
For small number of documents, unwind and match is fine. But large number of documents, it better to do - match ($elemMatch), unwind, and match again.
db.orders.aggregate(
{ "$match" : { "items" : { "$elemMatch" : { "qty" : { "$in" : [ 7]}}}}},
{ "$unwind" : "$items"},
{ "$match" : { "items.qty" : { "$in" : [7]}}}
...
...
);
The first match will filter only documents that match qty criteria. Among the selected documents, the second match will remove the subdocuments not matching the qty criteria.