How to check if multiple documents exist - mongodb

Is there such a query that gets multiple fields, and returns which of these exists in the collection?
For example, if the collection has only:
{id : 1}
{id : 2}
And I want to know which of [{id : 1} , {id : 3}] exists in it, then the result will be something like [{id : 1}].

You are looking for the $in-operator.
db.collection.find({ id: { $in: [ 1, 3 ] } });
This will get you any documents where the id-field (different from the special _id field) is 1 or 3. When you only want the values of the id field and not the whole documents:
db.collection.find({ id: { $in: [ 1, 3 ] } }, { _id: false, id:true });

If you want to check provided key with value is present or not in collection, you can simply check by matching values and combining conditions using $or operator.
By considering id is different than _id in mongo.
You can use $or to get expected output and query will be as following.
db.collection.find({$or:[{"id":1},{"id":3}]},{"_id":0,"id":1})
If you want to match _id then use following query:
db.collection.find({$or:[{"_id":ObjectId("557fda78d077e6851e5bf0d3")},{"_id":ObjectId("557fda78d077e6851e5bf0d5")}]}

Related

How to write a query to get the value for a specific key in "project_branch_config" field?

I have the following record in a collection ,I am trying to write a query to get the value for a specific key in "project_branch_config" field,my query db.getCollection('build_configs').find({"project_branch_config":"ACIWiFiDriver"}) doesn't yield anything?any guidance on how to fix this?
Also,should I structure my record differently (instead of a list of dictionaries) for this use-case?
Following is one record in my collection
{
"_id" : ObjectId("5d7fd4a33e398ff0cca87fe2"),
"train" : "trainB",
"project_branch_config" : [
{
"ACItechDriver" : "trainB"
},
{
"techCapture" : "trainB "
}
]
}
MY QUERY
db.getCollection('build_configs').find({"project_branch_config":"ACIWiFiDriver"})
CURRENT OUTPUT:-
Fetched 0 record(s) in 3ms
EXPECTED OUTPUT:-
{
"ACItechDriver" : "trainB"
},
In your question, I can you're querying for 'ACIWiFiDriver' but the expected OP is 'ACItechDriver'. I assume it is a typo
To check if the field exists use the below query:
db.build_configs.find({"project_branch_config.ACItechDriver": {$exists: true}}, {_id: 0, "project_branch_config.ACItechDriver": 1} )
To check if the field has specific value use the below query:
db.subdoc.find({"project_branch_config.ACItechDriver": "trainB"}, {_id: 0, "project_branch_config.ACItechDriver": 1} )

removing element of an array that with a match of certain element

I have a mongodb collection.
{ user_id: 1,
items : [ { _id: 1 }, { _id: 2}, {_id:3} ] }
I want to remove the items of the array having specific id. Can anybody explain what is wrong with the above query.
db.col.findOneAndUpdate({user_id:1},{$pull:{items:{$elemMatch:{_id:2}}}})
$pull takes an expression as a parameter so you don't have to use $elemMatch (doesn't work in this case). Try:
db.col.update({user_id:1},{$pull:{items:{_id:2}}})
So expression in this case means that MongoDB will remove the document having _id set to 2 but that document can have other properties as well.

Mongodb : How to find documents in which fields match an ObjectId or a string?

I have some documents in a collection in Mongodb :
{_id : ObjectId('533af69b923967ac1801e113'), fKey : '533aeb09ebef89282c6cc478', ... }
{_id : ObjectId('5343bd1e2305566008434afc'), fKey : ObjectId('5343bd1e2305566008434afc'), ...} }
As you can see my field fkey can be set by a string or an ObjectId.
I would like to get all documents which match '533aeb09ebef89282c6cc478' or ObjectId('5343bd1e2305566008434afc').
But if i run :
db.mycollection.find({fkey : '533aeb09ebef89282c6cc478'})
I only get the first document of the collection.
Is there a way to configure Mongodb in order to get all documents which match the request without checking the type ?
Thanks for your help.
Pierre
There are two options for you here.
You could use mongo's $or operator:
db.mycollection.find({
$or: [
{ fKey: '533aeb09ebef89282c6cc478' },
{ fKey: ObjectId( '533aeb09ebef89282c6cc478' ) }
]
})
The $or operator performs a logical OR operation on an array of two or more <expressions> and selects the documents that satisfy at least one of the <expressions>.
You could also use the $in operator:
db.mycollection.find({
fKey: {
"$in": [ '533aeb09ebef89282c6cc478', ObjectId( '533aeb09ebef89282c6cc478' ) ]
}
})
The $in operator selects the documents where the value of a field equals any value in the specified array.
It sounds to me like these inconsistencies are not meant to be there. I recommend going through your code and data pipelines and figure out who/what is inserting the fKey value with an unknown datatype.

MongoDB: Iterate over collection by key?

How can I iterate over all documents matching each value of a specified key in a MongoDB collection?
E.g. for a collection containing:
{ _id: ObjectId, keyA: 1 },
{ _id: ObjectId, keyA: 2 },
{ _id: ObjectId, keyA: 2 },
...with an index of { keyA: 1 }, how can I run an operation on all documents where keyA:1, then keyA:2, and so on?
Specifically, I want to run a count() of the documents for each keyA value. So for this collection, the equivalent of find({keyA:1}).count(), find({keyA:2}).count(), etc.
UPDATE: whether or not the keys are indexed is irrelevant in terms of how they're iterated, so edited title and description to make Q/A easier to reference in the future.
A simpler approach to get the grouped count of unique values for keyA would be to use the new Aggregation Framework in MongoDB 2.2:
eg:
db.coll.aggregate(
{ $group : {
_id: "$keyA",
count: { $sum : 1 }
}}
)
... returns a result set where each _id is a unique value for keyA, with the count of how many times that value appears:
{
"result" : [
{
"_id" : 2,
"count" : 2
},
{
"_id" : 1,
"count" : 1
}
],
"ok" : 1
}
I am not sure I get you here but is this what you are looking for:
db.mycollection.find({ keyA: 1 }).count()
Will count all keys with keyA being 1.
If that does not answer the question do think you can be a little more specific?
Do you mean to do an aggregation for all unique key values for keyA?
It may be implemented with multiple queries:
var i=0;
var f=[];
while(i!=db.col.count()){
var k=db.col.findOne({keyA:{$not:{$in:f}}}).keyA;
i+=db.col.find({keyA:k}).count();
f.push(k);
}
The sense of this code is to collect unique values of KeyA field of objects of col collection in array f, which will be result of operation. Unfortunately, for a while doing this operation you should block any operations, which will change col collection.
UPDATE:
All can be done much easier using distinct:
db.col.distinct("KeyA")
Thanks to #Aleksey for pointing me to db.collection.distinct.
Looks like this does it:
db.ships.distinct("keyA").forEach(function(v){
db.ships.find({keyA:v}).count();
});
Of course calling count() within a loop doesn't do much; in my case I was looking for key-values with more than one document, so I did this:
db.ships.distinct("keyA").forEach(function(v){
print(db.ships.find({keyA:v}).count() > 1);
});

How do I update Array Elements matching criteria in a MongoDB document?

I have a document with an array field, similar to this:
{
"_id" : "....",
"Statuses" : [
{ "Type" : 1, "Timestamp" : ISODate(...) },
{ "Type" : 2, "Timestamp" : ISODate(...) },
//Etc. etc.
]
}
How can I update a specific Status item's Timestamp, by specifying its Type value?
From mongodb shell you can do this by
db.your_collection.update(
{ _id: ObjectId("your_objectid"), "Statuses.Type": 1 },
{ $set: { "Statuses.$.Timestamp": "new timestamp" } }
)
so the c# equivalent
var query = Query.And(
Query.EQ("_id", "your_doc_id"),
Query.EQ("Statuses.Type", 1)
);
var result = your_collection.Update(
query,
Update.Set("Statuses.$.Timestamp", "new timestamp", UpdateFlags.Multi,SafeMode.True)
);
This will update the specific document, you can remove _id filter if you wanted to update the whole collection
Starting with MongoDB 3.6, the $[<identifier>] positional operator may be used. Unlike the $ positional operator — which updates at most one array element per document — the $[<identifier>] operator will update every matching array element. This is useful for scenarios where a given document may have multiple matching array elements that need to be updated.
db.yourCollection.update(
{ _id: "...." },
{ $set: {"Statuses.$[element].Timestamp": ISODate("2021-06-23T03:47:18.548Z")} },
{ arrayFilters: [{"element.Type": 1}] }
);
The arrayFilters option matches the array elements to update, and the $[element] is used within the $set update operator to indicate that only array elements that matched the arrayFilter should be updated.