Mongo Upsert with values of find $in - mongodb

I have to run mongo updates by querying that the user id is in an array. Is it possible to upsert any values not in the array?
Eg:
db.collection.update({
userId:{
$in:['1','2', '3']
}
},
{$set: {score:30}},
{upsert:true})
If I run this query I get one new doc with _id and score. What I'd like to do is have a new doc for each userId not present in the userId array:
[{userId:1, score:30, _id:...}, {userId:2, score: 30, _id: ...}, ...]
Is this possible in mongo?

No, this cannot be done. The documentation states:
If upsert is true and no document matches the query criteria, update() inserts a single document.

Related

How does mongodb use an index to count documents?

According to docs, db.collection.countDocuments() wraps this:
db.collection.aggregate([
{ $match: <query> },
{ $group: { _id: null, n: { $sum: 1 } } }
])
Even if there is an index, all of the matched docs will be passed into the $group to be counted, no?
If not, how is mongodb able to count the docs without processing all matching docs?
The MongoDB query planner can make some optimizations.
In that sample aggregation, it can see that no fields are required except for the ones referenced in <query>, so it can add an implicit $project stage to select only those fields.
If those fields and the _id are all included in a single index, there is no need to fetch the documents to execute that query, all the necessary information is available from the index.

MongoDB $merge with two fields being unique before insert?

Say I have a collection of elements with several fields, including userId and questionId. If I'm in an aggregation pipeline and I have a list of documents that all have userId and questionId as fields, but their values might already be in the collection (ie. a document of
{userId:1, questionId:1, score: 1}
but a similar document already exists in the collection
{userId:1, questionId:1, score:0}
How do I do a $merge into the collection while checking both fields? The $merge function does have an 'on: [field]' field to check overlap, but I don't think it can check two.
You can specify multiple fields in the on clause using an array.
db.toBe.aggregate([
{
"$merge": {
"into": "asIs",
"on": [
"userId",
"questionId"
],
"whenMatched": "merge"
}
}
])
Mongo Playground

What is the most efficient way to bulk toggle boolean value in mongodb?

I am trying to use aggregation pipeline and $not operator to bulk update fields of matched documents, but its not working.
I know but don't want to use js loop to modify them as it is inefficient way to do that.
let result = await User.updateMany(
{_id: {$in: ids}},
[{
$set: {isActive: {$not: ["$isActive"]}}
}]
)

MongoDB update collection's data

I try to update an MongoDB data by using this code:
db.medicines.update({"_id":"586a048e34e5c12614a7424a"}, {$set: {amount:'3'}})
but unfortantly the query does not recognize the selector "_id":"586a048e34e5c12614a7424a", even if its exists.
Its succsed when I change the key to another like: name,rate and etc..
there is a special way to use update with _id parameter?
Thanks a head.
_id will be the unique ObjectId that mongodb generates for every document before inserting it. The query dint work because _id is an ObjectId and "586a048e34e5c12614a7424a" is a String. You need to wrap _id with ObjectId().
If you're using mongodb query
db.medicines.update({
"_id": ObjectId("586a048e34e5c12614a7424a")
}, {
$set: {
amount: '3'
}
});
If you are using mongoose. You can use findByIdAndUpdate
db.medicines.findByIdAndUpdate({
"_id": "586a048e34e5c12614a7424a"
}, {
$set: {
amount: '3'
}
});

How to find document by parts of ObjectId?

For some reason I use MongoDB native ObjectId as primary key for ticket identification number for my application. Is it possible to search documents with ObjectId parts?
For example: I have documents:
[
{_id: ObjectId("577f8e6537e4a676203c056a")},
{_id: ObjectId("577f8ee437e4a676203c0577")},
{_id: ObjectId("577f8f3d717b6fdd22a1684c")}
]
And I want to query it by its _id contains "0577" so that it returns
{_id: ObjectId("577f8ee437e4a676203c0577")}
I have tried regex before. It returned []
db.transaction.find({_id: /0577/i}) ---> return 0
db.transaction.find({_id: {$regex: /0577/, $options: "i"}}) ---> return 0
I think you can use $where like this:
db.transaction.find({ $where: "this._id.str.match(/.*0577/)" })