Mongoose update specific fields in entire array of objects - javascript

In a mongoose document I have a array of objects, something like this :
{
name : 'helloWorld',
arr : [
{ a : 'id1', b : 'sampleValue1', c: 'sampleValue2'},
{ a : 'id2', b: 'tempValue1', c:'tempValue2'}
]
}
In the array of objects 'arr' I want to update all the values of field 'b' and 'c' with specific values, how can I do that elegantly?
I know for a single element of the array I can do (it works) :
Model.updateOne(
{
name : 'helloWorld;,
'arr.a' : 'id1',
},
{
'arr.$.b' : 'newB',
'arr.$.c' : 'newC',
}
);
But how to do it elegantly for the entire array ?
I know I can do it using multiple queries via forEach looping for each of the 'arr.a' field, but I want an elegant preferable single query method for this.

Related

Mongoose update inner field

I have this kind of documents in my mongoDB :
{
id: my_id
inner_foo : [
{
inner_id : id_A
inner_field : field_A
},
{
inner_id : id_B
inner_field : field_B
}
]
}
When receiving a request, i got two ids, the id one (here my_id), and the inner_id one (here for example id_A).
How can I, using JS and mongoose, update an inner field ? such as the inner_field field of one of the array contained objet using its inner_id
I think I cannot use findByIdAndUpdate since I can't make a direct reference to the correct inner_foo entry using that method, so how should I do it ?
Many thanks !
Kev.
Demo - https://mongoplayground.net/p/2pW4UrcVFYr
Read - https://docs.mongodb.com/manual/reference/operator/update/positional/
db.collection.update(
{ id: "my_id", "inner_foo.inner_id": "id_A" }, // find the matching document
{ $set: { "inner_foo.$.inner_field": "id_A_Update" }} // set the value on the matched array index
)

Dexie : How to add to array in nested object

I am using Dexie IndexedDB wrapper and I am trying to add an object to an existing array which in inside a nested object. The structure looks similar to below
{
Name : 'John',
age : 33,
tags : {
skill: [{
first: '.NET',
second: 'JAVA',
third: [{special1:'sleep'},{special2:'eat'}]
}]
}
}
I have tried many way to push object special3:'run' to skill.third but without success. My last attempt looked something like this
const pathObject = {};
const fullPath = 'result.tags.skill[3].third';
pathObject[fullPath] = {special3:'run'};
db.inspections.update(id, pathObject);
The object is added outside and not inside the array 'third' something like below
{
Name : 'John',
age : 33,
tags : {
skill: [{
first: '.NET',
second: 'JAVA',
third: [{special1:'sleep'},{special2:'eat'}]
}]
skill[3]: {
third: {special3:'run'}
}
}
}
I wish to know if there a way to add to arrays in nested object using Dexie if not is there a way to achieve this using indexeddb. Help is appreciated as problem is been holding back progress
The easiest is to use Collection.modify() with a callback function to mutate your model:
db.inspections.where('id').equals(id).modify(x =>
x.tags.skill[0].third.push({special3:'run'}) );
If you want to use a keypath containing array items, it is also possible, as arrays can be looked at as objects with numeric keys:
db.inspections.update(id, {"tags.skill.0.third.3": {special3:'run'}});

Array of Custom Objects MongoDB Schema

I need to create an array of objects with two fields (no methods needed) in mongoDB so that the document has a field that is an array of the these objects with two fields. I have no idea what the schema syntax should be however. How would I go about this?
Also:
Can I just declare an document with an array and fill it in with javascript objects created at run time?
Or should I declare the custom object in the Schema for the array holding document?
Thanks so much!
The following is an example creating an object with an array of object, each with 2 fields. Is this what you are looking for?
$ mongo
MongoDB shell version: 2.6.3
connecting to: test
>
>
> db.test.insert({myArray: [{a: 1, b: 2}, {a: 3, b:4}]})
WriteResult({ "nInserted" : 1 })
> db.test.findOne()
{
"_id" : ObjectId("53adc9301e7d2620fc75f8c7"),
"myArray" : [
{
"a" : 1,
"b" : 2
},
{
"a" : 3,
"b" : 4
}
]
}

execMatch only returning first result

I am trying to find a particular record (with an id of 1) and then to return only its history field. This history field is an array of objects with a timestamp property. When I return this history field, I want it to contain only objects with timestamp properties greater than 0.
Sample collection
[{
"_id" : 1,
"history" : [
{
"content" : "hello",
"timestamp" : 1394639953878,
"_id" : ObjectId("53208451767743b748ddbd7d")
},
{
"content" : "world",
"timestamp" : 1394639953879,
"_id" : ObjectId("33208451767743b748ddbd7e")
}
]
}]
Thus, according to Mongo and Mongoose documentation, I do something like:
model.find({_id: 1})
.select({ history: { $elemMatch: { timestamp: { $gt: 0 } } } });
The issue: I understand that there will only be one result (since I select the id 1) but I am using $elemMatch to populate its history field with all objects that have a timestamp greater than 0. The issue is that only one object is ever in history.
The $elemMatch projection returns only the first matching element satisfying the condition. Checkout the documentation.
Using aggregate would be the right approach to achieve what you want I think. Please see below:
db.bar.aggregate([
{$match:{_id:1}},
{$unwind:"$history"},
{$match:{"history.timestamp":{$gt:0}}},
{$group:{_id:"$_id", history:{$push:"$history"}}}
])

Using objects to store a list of names

I was wondering how to use an object to store a list of different names and access them by simply using the key.
Do I have to use embedded object like this.
var f =
{
0 : { name : "John" },
1 : { name : "Phillip" }
};
console.log(f[1].name);
Do not over-complicate things. Why don't you just try a simple array?
var f = [
{ name : "John" },
{ name : "Phillip" }
];
console.log(f[1].name);
Why not just an array, which is indexed identically? Do you actually need a name: attribute for some reason?
var names = [ 'John', 'Phillip' ];
Instead of names[0].name, which is pretty redundant, you'd just use names[0]...
He wants to access them by key:
var people = {
John:{ age:33},
Bob :{ age:42}
};
Now you can truly access them by key:
console.log(people["John"].age);
or this way (although odd):
console.log(people.John.age);
No looping is necessary, you are using the power of javascripts associative syntax to index directly into your data structure. No need to refer to some arbitrary integer index either.
This definitely works but typically you'd use a more appropriate property to index than just a name like perhaps an employee id.
You can use like this
Var names = [
{ 'name' : 'ashwin', age: 18 },
{'name' : 'jhon', 'age' : 20 }
];
console.log ( names[0].name );

Categories

Resources