Increment nested field value in mongodb if exists or create nested fields - node.js

I need to increment the multi level nested field value if it exists or create the complete nested field Object structure.
Structure of my document
Doc1 {
_id:ObjectId(),
myField: {
nested:{
x: 5,
y: 10,
z: 20
}
}
}
Goal Explanation: I need a way to write a single query:
If myField exists: Increment the value of my nested field
myField.nested.x by 10.
If myField does not exists: Create the below field with initial values same as given in the Doc1.
Attempt and explanation:
db.collection('collectionName').findOneAndUpdate(
{_id:"userId","myField" : { $exists : true }},
{$inc:{'myField.nested.x':10}
})
This way, I can increment the nested field if it exists but in case of non existence I cannot set myField as same as Doc1.
Although, I can use another query after response in my NodeJs callback to achieve my required behaviour. But I need some elegant solution in a single query.
I am using MongoDB version 4.0.4, Thanks in Advance.

Try this query
If the field does not exist, $inc creates the field and sets the field to the specified value.
db.collection('collectionName').findOneAndUpdate({_id:"userId"},
{$inc:{'myField.nested.x':10}
})

Related

Update specific field in an array of object in a MongoDb Document

I have a document with that format :
{
"field1":"string",
"field2":123,
"field3":
[
{
"subField1":"string",
"subField2": object,
// other fields after
},
{
"subField1":"string",
"subField2": object,
// other fields after
},
// other fields after
]
// other fields after
}
I want to update at once the field3.$.subField2 field only, with a different value in each of the elements of the array composing field3.
Does anyone knows how to properly do it ?
One reason I want to do this is I have several asynchronous operations that are meant to update differents fields of the array field, and I have concurrency issues...
I tried with findOneAndUpdate(query, $set{"field3.$.subField2": arrayOfValues}) but it does not works, it seems I can only pass one single value that would be set to each element of the array (all the same).
arrayOfValues would be of course an array with only the values I want with the matching indexes and same size of the document's array.

How to query field exist some document in firebase

I using firebase, nodejs and i have a question how to query field exist some document.
Example :
Collections : users => document : A with field {
....
is_correct: true
}
document : B with field {
.....
}
In my above example , i have two document in collection users. On document A i have field is_correct: true and on document B field is_correct not exist.
My collection users about 15.000 document and it have 50 document contain field is_correct: true
When i write code look like :
await firestore.collection('users').where('is_correct', '==', true).get();
it can get correct me 50 document. But i don't understand it can using index on field is_correct or not ? And it can query best performance ? I understand firebase can't get document if field undefined. It impart in case ? Please help ? Thanks you
For a simple query like
firestore.collection('users').where('is_correct', '==', true)
you don't need to configure any index, Firestore does it automatically.
As you mentioned, only documents where the given field exists can match the query.
And this is the case also for Not-equal (!=) and not-in queries: they exclude documents where the given field does not exist, as explained in the documentation.
Also, note that a field exists when it's set to any value, including an empty string (""), null, and NaN (not a number).
So, in conclusion, if you want to query for documents where is_correct is not true, you need to create this field in these documents with a value different than true.

Mongodb: can I compare if value in one field is contained in another field

Suppose I have a collection a called collection_a that contains a lookup to a collection b called collection_b. If the collection contains a field called primary_color and the lookup contains a field called available_colors. How can I compare primary_color to available_colors to see if the current value for primary_color is contained in the available_colors list?
I tried the following but it did not work in a aggregate match,
{'primary_color': {'$in': '$collection_b.available_colors'}}.
It is not possible to refer another collection in $match stage.
You have to use $lookup or populate in mongoose.
db.collectiona.aggregate([
{"$lookup":{
"from":collectionb,
"localField":"primary_color",
"foreignField":"available_colors",
"as":"matches"
}},
{"$match":{"matches.0":{"$exists":true}}}
])
https://mongoplayground.net/p/bkQzZcrP0aJ

Is there any way to create partial index in ArangoDB?

I want to create partial index for the collection, but the index should be applied to documents by conditions. For example, I want to check uniqueness of documents only if they have the certain field value. In other words, I'm looking for some construction of index creating:
db.person.createIndex(
{ age: 1},
{ partialFilterExpression: { age: { $gte: 18 }}
);
This example is from MongoDB and it is applying index on documents with field 'age' value greater then 18
There is no way to create a "filtered index" (like you can in SQL). According to the docs, you can include attributes, but not conditionally.
You could try a sparse index, but I think your best bet is adding the age attribute to a "skiplist" index, which supports sorting and gt/lt evaluation.
Make sure you use the explain feature to validate index usage.

Sort by a array element (document) field - MongoDB/Mongoose

This is the concerned part from the schema
`
var CandidateSchema = new Schema({
calculateScore:[{
jobname:{type:Schema.ObjectId,ref: 'Job'}
,Score:{type:Number,default:0}
}]
})
`
A candidate can apply to multiple jobs and get scored differently for different jobs. I want to sort the candidates depending on the specific job's Score. Any Idea?
Assuming the variable objectId holds the ObjectId of the referred Job, you can aggregate the records to get the records sorted by the score of that particular Job.
Since the stage operator $project does not support the $elemeMatch operation, we cannot use it to directly get the Job sub document that we want and sort based on it.
$project a separate field named temp_score to have a copy of the original calculateScore array.
$redact other sub documents from calculateScore other than whose jobname contains the
id we are looking for. Now calculateScore will contain only one
element in the array, i.e the element whose jobname is the id
that we have specified.
Based on this sub document's score sort the records in descending
order.
Once the sorting is done, project our original calculatescore
field, which is in temp_score.
The code:
var objectId = ObjectId("ObjectId of the referred Job"); // Needs to be fetched
// from the Job collection.
model.aggregate(
{$project:{"temp_score":{"level":{$literal:1},
"calculateScore":"$calculateScore"},
"calculateScore":1}},
{$redact:{$cond:[
{$and:[
{$eq:[{$ifNull:["$jobname",objectId]},objectId]},
{$ne:["$level",1]}
]
},
"$$DESCEND",
{$cond:[{$eq:["$level",1]},
"$$KEEP","$$PRUNE"]}]}},
{$sort:{"calculateScore.Score":-1}},
{$project:{"_id":1,
"calculateScore":"$temp_score.calculateScore"}},
function(err,res)
{
console.log(res);
}
);

Resources