MongoDB return only matched sub-sub document - mongodb

Given the above document structure, in mongodb, how do you guys filter a specific terminal whose id matches the given parameter?

Assuming your JSON looks like this, or similar:
{
"Merchant_Account":"Merchant Name",
"ID":"MA1",
"Card_Acceptor":[{
"ID":"CA1",
"Vendor_ID":{
"ID":"VID1"
},
"Terminal_ID":[
"TID1",
"TID2",
"TID3"
]
}]
}
You can retrieve this document using the following in Mongo Shell:
db.collection.find({"Card_Acceptor":{$elemMatch:{Terminal_ID:"TID1"}}})
This returns the whole document where a Terminal ID matches in the array of Terminal_IDs. The key here is the $elemMatch array query operator.

Related

How to update all documents based on whether an array contains a specific element in pymongo?

I have been trying with this:
self.followersDbRef.update({'followersList':{'$elemMatch':{'$eq':userID}}},{'$addToSet':{'feed':postDict},'$set':{'_id':userID}},multi=True,upsert=True)
but to no avail.
Instead another document is created altogether.
It should be such that whenever I add a post all other users that follow me will get the post copied to their feed.
In mongoDB the basic query { key: "value" } matches both for exact match and for match within an array. So if your data looks like this:
{"key": "a"},
{"key": ["a", "b"]}
Then the following query will match both documents:
db.collection.find({"key": "a"})
With that in mind, this is probably what you're looking for:
self.followersDbRef.update(
{'followersList': userID},
{'$addToSet': {'feed':postDict},'$set':{'_id':userID}},
multi=True,
upsert=True
)
Also note that upsert means that if no match is found, a document will be inserted instead. If you do not want that to happen, you can remove upsert=True or change it to False.

Mongoose Updating an array in multiple documents by passing an array of filters to update query

I have multiple documents(3 documents in this example) in one collection that looks like this:
{
_id:123,
bizs:[{_id:'',name:'a'},{_id:'',name:'b'}]
},
{
_id:456,
bizs:[{_id:'',name:'e'},{_id:'',name:'f'}]
}
{
_id:789,
bizs:[{_id:'',name:'x'},{_id:'',name:'y'}]
}
Now, I want to update the bizs subdocument by matching with my array of ids.
That is to say, my array filter for update query is [123,789], which will match against the _id fields of each document.
I have tried using findByIdAndUpdate() but that doesn't allow an array for the update query
How can I update the 2 matching documents (like my example above) without having to put findByIdAndUpdate inside a forloop to match the array element with the _id?
You can not use findByIdAndUpdate when updating multiple documents, findByIdAndUpdate is from mongoose which is a wrapper to native MongoDB's findOneAndUpdate. When you pass a single string as a filter to findByIdAndUpdate like : Collection.findByIdAndUpdate({'5e179dac627ef7823643cd97'}, {}) - then mongoose will internally convert string to ObjectId() & form it as a filter like :_id : ObjectId('5e179dac627ef7823643cd97') to execute findOneAndUpdate. So it means you can only update one document at a time, So if you've multiple documents to be updated use update with option {multi : true} or updateMany.
Assume if you wanted to push a new object to bizs, this is how query looks like :
collection.updateMany({ _id: { $in: [123, 456] } }, {
$push: {
bizs: {
"_id": "",
"name": "new"
}
}
})
Note : Update operations doesn't return the documents in response rather they will return write result which has information about n docs matched & n docs modified.

MongoDB - Querying a field in a lower level of document

Issue with fetching the data of a particular field within a document
The followoing is my collection structure
colleciton mail
mailtype
criteria
triggerinfor
code ----> multiple codes are there.
description
status
Tried this but not working
db.getCollection('Mail').find(
{
"MailType" :"Printed",
"MailName" :"Welcomemail",
"programType":"Maile",
"criterias" :
{"triggerInformation":
{"code" :"MAIL007"},
{"description":"1234 Welcome maile"}
}
}
)
I have to retrieve the document with code MAIL007 only.. could some one help in getting a query for that
There are two ways to do it, depending on what you need:
1- Matching an exact nested document: this way, you are querying for documents that have a nested document that is exactly like the one in your search criteria.
db.getCollection('Mail').find(
{
"MailType" :"Printed",
"MailName" :"Welcomemail",
"programType":"Maile",
"criterias.triggerInformation": {
"code": "MAIL007",
"description": "1234 Welcome maile",
"status": "some status"
}
}
Notice that you need to explicitly inform a value to each of the nested document fields in your search criteria. If any field is missing the query will return nothing.
2- Querying a field inside a nested document: this way, you are querying for documents based on the value of one or more fields inside a nested document.
db.getCollection('Mail').find({
"MailType":"Printed",
"MailName":"Welcomemail",
"programType":"Maile",
$and: [
{"criterias.triggerInformation.code": "MAIL007"},
{"criterias.triggerInformation.description": "description":"1234 Welcome maile"}
]
})
In the code above you are querying for documents based on the values of the fields code and description inside the nested document criterias.triggerInformation.
You can find more info about querying nested documents at MongoDB's docs here

How to I ensure that all items in an $in clause return a match in MongoDB?

I am working with a set of documents like this:
{
name : "BCC 204",
//etc
}
I have a list of names that I want to map to their DB entries.
For example:
var names = [ "BCC 204", "STEW 101", "SMTH 123" ]
and I want to make a query like this
db.labs.find( { name : { $in: names } } );
But the $in operator does not ensure that each item in the names array matches a result in the db.
(More info, names are unique)
You can't do this in the query. $in will check that a document matches at least one entry in the array given, but it's not going to consider the entire result set. This is a concern you'll need to manage in your application. Given a list of inputs, you will need to retrieve your results then check that given_names - results.map(:name) is empty.
To put it more simply, queries match documents, which compose a result set - they don't match a result set.

How to read a specific key-value pair from mongodb collection

If I have a mongodb collection users like this:
{
"_id": 1,
"name": {
"first" : "John",
"last" :"Backus"
},
}
How do I retrieve name.first from this without providing _id or any other reference. Also, is it possible that pulling just the `name^ can give me the array of embedded keys (first and last in this case)? How can that be done?
db.users.find({"name.first"}) didn't work for me, I got a:
SyntaxError "missing: after property id (shell):1
The first argument to find() is the query criteria whereas the second argument to the find() method is a projection, and it takes the form of a document with a list of fields for inclusion or exclusion from the result set. You can either specify the fields to include (e.g. { field: 1 }) or specify the fields to exclude (e.g. { field: 0 }). The _id field is implicitly included, unless explicitly excluded.
In your case, db.users.find({name.first}) will give an error as it is expected to be a search criteria.
To get the name json :
db.users.find({},{name:1})
If you want to fetch only name.first
db.users.find({},{"name.first":1})
Mongodb Documentation link here
To fetch all the record details:
db.users.find({"name.first":""})
To fetch just the name or specific field:
db.users.find({{},"name.X":""});
where X can be first, last .
dot(.) notation can be used if required to traverse inside the array for key value pair as
db.users.find({"name.first._id":"xyz"});
In 2022
const cursor = db
.collection('inventory')
.find({
status: 'A'
})
.project({ item: 1, status: 1 });
Source: https://www.mongodb.com/docs/manual/tutorial/project-fields-from-query-results/