How to push new items to an array inside of an object - javascript

My JSON currently looks like this:
{
"_id" : 393,
"item" : 34,
"comments" : [
{
"name" : "kevin",
"messages" : [
"item",
"item"
]
},
{
"name" : "ryan",
"messages" : [
"item",
"item"
]
}
]
}
How could I push new items onto the messages array for the first or second item in the comments array?
db.newcon.update({_id: 393}, { $push: { comments['kevin']: {messages: 39 } } })

Using $elemMatch and $ operator you can update your documents check below query :
db.collectionName.update({"_id":393,"comments":{"$elemMatch":{"name":"kevin"}}},
{"$push":{"comments.$.messages":39}})

Something like this will work:
var newMessage = '39';
comments.forEach(function(item) {
if (item.name === 'kevin') {
item.comments.push(newMessage);
}
});

Related

How can i optimize below query in Mongoose?

Basically, I want to fetch data from collection where pincode field(inside Location array) is matched by req.body
I'm getting my desired output but I'm not sure if it's a optimized way or not (look in Mongoose query part)
Here's my Json:
{
"_id" : ObjectId("6115b2cc1681596a10072f97"),
"vendorStatus" : "Active",
"name" : "harshit singh bhutani",
"email" : "sharsh2106#gmail.com",
"vId" : 12121,
"contact" : 121212,
"cities" : "dell",
"isMidnight" : "NA",
"location" : [
{
"delivery" : 1266,
"dc" : "High",
"midnight" : "Active",
"isLive" : "NA",
"_id" : ObjectId("612433c27292d11154bc4d4d"),
"pincode" : 123100,
"city" : "dek"
},
{
"delivery" : 23,
"dc" : "High",
"midnight" : "Active",
"isLive" : "NA",
"_id" : ObjectId("612441473cb5766a2457d6db"),
"pincode" : 1212,
"city" : "dd"
}
],
"createdAt" : ISODate("2021-08-12T23:46:20.407Z"),
"updatedAt" : ISODate("2021-09-03T10:51:34.756Z"),
"__v" : 73
}
Here's my query in Mongoose:
const { pin } = req.body;
const vendor = await Vendor.find({ vendorStatus: "Active" });
const pincode = vendor.map((item) => {
return item.location.find((i) => {
if (i.pincode === Number(pin) && i.isLive === "Active") {
return i;
}
});
});
const pincodefound = pincode.filter(Boolean);
if (pincodefound.length === 0) {
res.status(404);
throw Error("Product is not Deliverable at this Pincode");
} else {
return res.json({
pincodefound,
});
}
First I use map to iterate then I used find to grab the matched pincode after that I'm getting array with output and null value so I use filter to get only pincode
though I get my desired output BUT still I'm not sure weather its a optimized approach or not.
If I understood correctly your JS code you want to get only the value into the location array which match the condition.
In this case is a better way to do everything in a query. You can use an aggregation pipeline.
This query:
First match by vendorStatus: "Active like your find query.
Then use $unwind to deconstruct the array and look in each value.
$match to find a value which pincode and isLive are desired values.
And last stage is $project to show only values you want, in this case, the location values.
const pincode = await Vendor.aggregate([
{
"$match": {
"vendorStatus": "Active"
}
},
{
"$unwind": "$location"
},
{
"$match": {
"location.pincode": pin,
"location.isLive": "Active"
}
},
{
"$project": {
"delivery": "$location.delivery",
"dc": "$location.dc",
"midnight": "$location.midnight",
"isLive": "$location.isLive",
"_id": "$location._id",
"pincode": "$location.pincode",
"city": "$location.city"
}
}
]);
Example here

Convert Object to Array For a User In MongoDB

I have multiple users in my collection and each user has an object of sessions shown below
{
user: 'adam',
sessions: {
key: some-value,
key: some-value
}
}
{
user: 'chris',
sessions: {
key: some-value,
key: some-value
}
}
I fetch the document on the basis of the user name. let us say i want the sessions of adam.
So I run db.collection.find({ user: 'Adam' }) which gives me full document of adam. Now I want the sessions of 'Adam' but the sessions object should be converted into an array of objects like this :
{
user: 'adam'
sessions : [ { key: value },{ key: value } ]
}
I want to convert the sessions of user into an object that means i want to do $objectToArray but on a specific username not the full collection.
Just the user I want.
Explanation:
I am running node as backend and i have a route called 'getuserdata' which gets data for a specific user based on the username. So when i will hit that route with username adam and it will get the data from the DB. The sessions of adam should come in an array of objects like shown above instead of an object which is in the db.
What i am doing
I am running a for-in loop on the back-end to convert them into array of objects but it is slow.
You can do it using $map in project part,
$map input sessions as array to convert using $objectToArray,
inside map convert array of object key and value to $arrayToObject
db.collection.find(
{ user: "adam" },
{
user: 1,
sessions: {
$map: {
input: { $objectToArray: "$sessions" },
in: { $arrayToObject: [["$$this"]] }
}
}
})
Playground
//run from mongodb client
//sample user data preparation
> db.users15.find();
{ "_id" : ObjectId("5f4fbfbc3372ab5da3a605ac"), "user" : "adam", "sessions" : { "key1" : 1123, "key2" : 1124 } }
{ "_id" : ObjectId("5f4fbfbc3372ab5da3a605ad"), "user" : "chris", "sessions" : { "key1" : 2122, "key2" : 2134 } }
// Mongo query, variable defined an user for dynamic passing in match condition
> var v_user = "adam"
> db.users15.aggregate([
... {$match:{user:v_user}},
... {$project:{user:1,
... sessionArray:{$objectToArray:"$sessions"}
... }
... }
... ]);
//output showing conversion from session object to array for key value pair
{ "_id" : ObjectId("5f4fbfbc3372ab5da3a605ac"), "user" : "adam", "sessionArray" : [ { "k" : "key1", "v" : 1123 }, { "k" : "key2", "v" : 1124 } ] }
>
//Further,the mongo query gives correct output for nested objects as well.
//Example below.
> db.users15.find().pretty();
{
"_id" : ObjectId("5f4fbfbc3372ab5da3a605ac"),
"user" : "adam",
"sessions" : {
"key1" : 1123,
"key2" : 1124
}
}
{
"_id" : ObjectId("5f4fbfbc3372ab5da3a605ad"),
"user" : "chris",
"sessions" : {
"key1" : 2122,
"key2" : 2134
}
}
{
"_id" : ObjectId("5f5069ed3372ab5da3a605ae"),
"user" : "sriny",
"sessions" : {
"key1" : 2122,
"key2" : 2134,
"key3" : {
"server1" : 2344,
"server2" : 9999
}
}
}
>
> var v_user = "sriny"
> db.users15.aggregate([
... {$match:{user:v_user}},
... {$project:{user:1,
... sessionArray:{$objectToArray:"$sessions"}
... }
... }
... ]).pretty();
{
"_id" : ObjectId("5f5069ed3372ab5da3a605ae"),
"user" : "sriny",
"sessionArray" : [
{
"k" : "key1",
"v" : 2122
},
{
"k" : "key2",
"v" : 2134
},
{
"k" : "key3",
"v" : {
"server1" : 2344,
"server2" : 9999
}
}
]
}
>
Take for example this object
const obj = {
key1: "value1",
key2: "value2"
}
We can map this to pattern [ { key1: value1 }, { key2: value2 } ] using a map on the object keys
const arrayFromObj = Object.keys(obj).map(value => {
return { value: obj[value] }
})

Simplify forEach statement to update a mongoDB document with nested objects and arrays

I'd like to update the value of the key shouldSendAlert in the following document:
{
"_id" : ObjectId("5c61c4db46d18e1092c5b024"),
"service" : "SRVPVD",
"menu" : [
{
"sub" : [
{
"options" : [
{
"item" : [
{
"name" : "",
"actions" : [
{
"name" : "communicateClient",
"value" : true
},
{
"name" : "shouldSendAlert",
"value" : false
}
]
}
],
"name" : "Technology Support"
},
{
"item" : [
{
"name" : "",
"actions" : [
{
"name" : "communicateClient",
"value" : true
}
]
}
],
"name" : "Company Support"
}
],
"name" : "Support"
},
{
"name" : " FAQ"
}
],
"name" : "Help"
}
]
}
I've managed to do this, querying the document using a multiple $elemMatch query, and using forEach to run through the nested arrays in order to alter the value of shouldSendAlert:
{
let menuItems = db.getCollection('menumodels').find({menu: {$elemMatch: {name: 'Help',sub: {$elemMatch: {name: 'Support',motivos: {$elemMatch: {name: 'Technology Support'}}}}}}});
menuItems.forEach((r) => {
r.menu.forEach(menuItem => {
if (menuItem.name == 'Help') {
menuItem.sub.forEach(sub => {
if (sub.name == 'Support') {
sub.motivos.forEach(motivo => {
if (motivo.name == "Technology Support") {
motivo.item[0].actions.forEach(action => {
if (action.name == 'shouldSendAlert') {
action.value = true;
db.getCollection('menumodels').update({_id: r._id}, {$set: {menu: r.menu}})
}
})
}
})
}
})
}
})
});
}
Is it - regarding performance - necessary, to code this MongoDB query
or update logic into a smarter form? Does the multiple use of $elemMatch affect performance?

mongoDB: Can't add an field to an array object

This is how my db document looks like:
{
"_id" : "aN2jGuR2rSzDx87LB",
"content" : {
"en" : [
{
"content" : "Item 1",
"timestamp" : 1518811796
}
]
}
}
Now I need to add another field in the first object of the content.en array.
The document itself gets selected by an ID.
The result should be:
{
"_id" : "aN2jGuR2rSzDx87LB",
"content" : {
"en" : [
{
"content" : "Item 1",
"timestamp" : 1518811796,
"user" : {
"id" : 'userId'
}
}
]
}
}
I tried to do it like this, but nothing is happening. I don't even get an error message.
Content.update(
{ _id: id },
{
$addToSet: {
'content.en.0.user': {
id: 'userId',
}
}
}
)
Also I would like to use an variable for the language. How do I do that? Something like 'content.' + language + '.0.user'...
$addToSet is useful when you want to add someting to an array. In your case you want to modify first element of your array (at index 0) so you should simply use $set (which is field update operator):
Content.update(
{ _id: "aN2jGuR2rSzDx87LB" },
{
$set: {
"content.en.0.user": {
id: "userId",
}
}
}
)

Updating array inside two object in mongod

I have a collection of the structure as follows:
collection name : "positions"
Structure
{
"_id" : "vtQ3tFXg8THF3TNBc",
"candidatesActions" : {
"sourced" : [ ],
},
"appFormObject" : {
"name" : "✶ mandatory",
"questions" : [
{
"qusId" : "qs-585494",
"type" : "simple",
"qus" : "Which was your previous company"
},
{
"qusId" : "qs-867766",
"type" : "yesNo",
"qus" : "Are you willing to relocate?",
"disqualify" : "true"
}
]
}
}
I want to update "qus" field of the above collection whose _id is "vtQ3tFXg8THF3TNBc" and "qusId" is "qs-585494".
Try following....
db.positions.update(
{_id: "vtQ3tFXg8THF3TNBc", "appFormObject.questions.qusId":"qs-585494"},
{$set:{"appFormObject.questions.$.qus": "this is updated value"}}
)
Use following query
db.positions.findAndModify({
query: { _id: "vtQ3tFXg8THF3TNBc", "appFormObject.questions.qusId":"qs-585494"} ,
update: { $set: { 'appFormObject.questions.$.qus': 'Brilliant Green' } },
});
Thanks

Categories

Resources