Insert array into sub-sub-document in mongoDB [duplicate] - arrays

I want add new data my nested array
My document is:
{
"username": "erkin",
"email": "erkin-07#hotmail.com",
"password": "b",
"playlists": [
{
"_id": 58,
"name": "asdsa",
"date": "09-01-15",
"musics": [
{
"name": "INNA - Cola Song (feat. J Balvin)",
"duration": "3.00"
},
{
"name": "blabla",
"duration": "3.00"
}
]
}
]
}
I want add music in this playlist section:
{
"username": "erkin",
"email": "erkin-07#hotmail.com",
"password": "b",
"playlists": [
{
"_id": 58,
"name": "asdsa",
"date": "09-01-15",
"musics": [
{
"name": "INNA - Cola Song (feat. J Balvin)",
"duration": "3.00"
},
{
"name": "blabla",
"duration": "3.00"
},
{
"name": "new",
"duration": "3.00"
}
]
}
]
}
Here is what I tried:
$users->update(
array(
'_id' => new MongoId (Session::get('id')),
'playlists._id' => $playlistId
),
array(
'$push' => array('playlists.musics' => array(
'name' => 'newrecord',
'duration' => '3.00'
))
)
);

Probably something like this where ID is your ObjectId. The first {} are necessary to identify your document. It is not required to use an ObjectId as long as you have another unique identifier in your collection.
db.collection.update(
{ "_id": ID, "playlists._id": "58"},
{ "$push":
{"playlists.$.musics":
{
"name": "test name",
"duration": "4.00"
}
}
}
)

This way it worked for me!
"playlists.$[].musics":
db.collection.update(
{ "_id": ID, "playlists._id": "58"},
{ "$push":
{"playlists.$[].musics":
{
"name": "test name",
"duration": "4.00"
}
}
}
)
https://docs.mongodb.com/manual/reference/operator/update/positional-filtered/#position-nested-arrays-filtered

I suggest you using arrayFilters since it supports multiple nested documents and clearer.
db.collection.update(
{ "_id": ID},
{ "$push":
{"playlists.$[i].musics":
{
"name": "test name",
"duration": "4.00"
}
}
},
{
arrayFilters: [
{'i._id': 58,},
],
},
)

2022 update:
Full snippet:
from pymongo import MongoClient
client = MongoClient('mongodb://localhost:27017/', maxPoolSize=50)
db = client.name_of_db
collection = db["name_of_collection"]
To push:
collection.find_one_and_update(
{"_id": 'id_of_the_document'},
{"$push": {"key":"value"}})
To push into nested:
collection.find_one_and_update(
{"_id": 'id_of_the_document'},
{"$push": {"key.nested_key":"value"}})

Related

MongoDB: find sum of nested array elements

Let's say I have a Customer document like the following
db.collection.insertOne( {
"customerName": "John Doe",
"orders": [
{
"type": "regular",
"items": [
{
"name": "itemA",
"price": 11.1
},
{
"name": "itemB",
"price": 22.2
}
]
},
{
"type": "express",
"items": [
{
"name": "itemC",
"price": 33.3
},
{
"name": "itemD",
"price": 44.4
}
]
}
]
})
How can I calculate the total price of all orders (111 in this example)?
You can $unwind twice (because nested array) and group using $sum like this:
db.collection.aggregate([
{
"$unwind": "$orders"
},
{
"$unwind": "$orders.items"
},
{
"$group": {
"_id": "$customerName",
"total": {
"$sum": "$orders.items.price"
}
}
}
])
Example here

How do i update same field when it is array of object in mongodb

This is example of field:
Document1:
comments: [
{
"_id": "6040840",
"user_id": "600d4fd",
"text": "very nice post",
"res_comment": [
{
"_id": "39834",
"user_id": "6acd4fd",
"text": "thanks"
},
{
"_id": "6983b9634",
"user_id": "6005afd",
"text": "yeah!!"
}
]
},
{
"_id": "6040840a",
"user_id": "6004fd",
"text": "very nice post",
"res_comment": [
{
"_id": "3983b9634",
"user_id": "6acd4fd",
"text": "thanks"
},
{
"_id": "6983b9",
"user_id": "6005afd",
"text": "yeah!!"
}
]
}
]
So now i want to pull from comments
index 0 whole element which _id 6040840 and
index 1 only pull res_comment which _id 6983b9
In single Update query.
Anyone having solution for this.
$ https://docs.mongodb.com/manual/reference/operator/update/positional/
db.collection.updateOne({
"res_comment._id": "6983b9634"
},
{
$set: {
"res_comment.$.text": "hello"
}
})

How to replace a value of an array in MongoDB aggregation?

I'm trying to replace the value only in the aggregation result, not in the stored document, thats why I use an aggregation and not a update.
Suppose these are the documents stored in the collection:
{ "_id": 1, "first_name": "foo1", items: [
{ "item": "gloves", "body": "hands" },
{ "item": "gloves", "body": "hands" },
{ "item": "shirts" , "body": "torso" }
]
},
{ "_id": 2, "first_name": "foo2", items: [
{ "item": "skirts", "where": "legs" },
{ "item": "jeans", "body": "legs" },
{ "item": "socks" , "body": "feet" },
{ "item": "gloves" , "body": "hands" }
]
},
{ "_id": 3, "first_name": "foo3", items: [
{ "item": "jacket", "where": "torso" },
{ "item": "socks", "body": "feet" },
{ "item": "shirts" , "body": "torso" }
]
}
The aggregation must replace "gloves" by "sandals", and it correspondent attribute "body" from "hands" to "feet".
The expected result is:
{ "_id": 1, "first_name": "foo1", items: [
{ "item": "sandals", "body": "feet" },
{ "item": "sandals", "body": "feet" },
{ "item": "shirts" , "body": "torso" }
]
},
{ "_id": 2, "first_name": "foo2", items: [
{ "item": "skirts", "where": "legs" },
{ "item": "jeans", "body": "legs" },
{ "item": "socks" , "body": "feet" },
{ "item": "sandals" , "body": "feet" }
]
},
{ "_id": 3, "first_name": "foo3", items: [
{ "item": "jacket", "where": "torso" },
{ "item": "socks", "body": "feet" },
{ "item": "shirts" , "body": "torso" }
]
}
So far, I've tried using "$unwind" and $project with "$switch", among other approaches, but none of them work.

How to use array pluck to get key values from a multidemensional array in Laravel?

I have the following multidemensional array:
[
{
"city": {
"name": "New York",
"country": "Usa",
"geolocation": {
"lat": "40.7142691",
"lon": "-74.0059729"
},
},
"experiences": [
{
"title": "foobar",
"id": "54095f19ca04fffa8791ecae"
},
{
"title": "foobar_foo",
"id": "54e1bff02f16a457c00ea171"
}
[...]
]
},
{
"city": {
"name": "San Francisco",
"country": "Usa",
"geolocation": {
"lat": "37.7749295",
"lon": "-122.4194155"
},
},
"experiences": [
{
"title": "foobar",
"id": "53e4db618027d69eab65f2ce"
},
{
"title": "foobar_bar",
"id": "54afbeb7abdf8e3d30bd5993"
}
[...]
]
}
]
I need to create a new array filled with the IDs of each experience in the above array, something like:
["id" = "foo123", "id" => "foo456", "id" => "foo789", "id" => "fooabc"]
I've tried using laravel's helper Arr::pluck but it returns null:
Arr::pluck($myArr, "experiences.id")
[null, null, null]
How can I do this?
Try
$res = [];
foreach($data as $key => $value)
{
foreach($value['experiences'] as $exp)
{
$res[] = $exp['id'];
}
}
dd($res);
Output will be
array:4 [
0 => "54095f19ca04fffa8791ecae"
1 => "54e1bff02f16a457c00ea171"
2 => "53e4db618027d69eab65f2ce"
3 => "54afbeb7abdf8e3d30bd5993"
]

How can I get unique array from a collection of nested objects with lodash?

I have the following collection:
"items": [{
"id": 1,
"title": "Montrachet",
"imageUrl": "http://winebuff.com.hk/products_image/3376-Ramonet-ChassagneMontrachetBlanc.jpg",
"imageUrls": [
"http://winebuff.com.hk/products_image/3376-Ramonet-ChassagneMontrachetBlanc.jpg",
"http://media.riepenau.com/wines/17973_b.jpg",
"http://lorempixel.com/400/400/food/3"
],
"properties": [
{"description" : "Kırmızı Şaraplar Desc"},
{"region" :"Bordeaux"},
{"age": "16"},
{"producer" :"Kayra"},
{"grapeType":"Espadeiro"}
],
"priceGlass": "1",
"priceBottle": "2",
"year": "1999"
},
{
"id": 2,
"title": "Montrachet2",
"imageUrl": "http://winebuff.com.hk/products_image/3376-Ramonet-ChassagneMontrachetBlanc.jpg",
"imageUrls": [
"http://winebuff.com.hk/products_image/3376-Ramonet-ChassagneMontrachetBlanc.jpg",
"http://media.riepenau.com/wines/17973_b.jpg",
"http://lorempixel.com/400/400/food/3"
],
"properties": [
{"description" : "Kırmızı Şaraplar Desc"},
{"region" :"Bordeaux"},
{"age": "16"},
{"producer" :"Kayra"},
{"grapeType":"Chardonnay"}
],
"priceGlass": "1",
"priceBottle": "2",
"year": "1999",
}
]
I want to grab unique grapeTypes from that collection. The returning array shold be ["Chardonnay","Espadeiro"]
What is the best way to do it with lodash?
I think this combination of pluck, map and filter should do it:
var result = _.chain(obj.items).pluck('properties').map(function(obj) {
return _.filter(obj, function(prop) {
return prop.grapeType;
})[0].grapeType;
}).uniq().value();
console.log(result);
Check the demo run below.
// Code goes here
var obj = {
items: [{
"id": 1,
"title": "Montrachet",
"imageUrl": "http://winebuff.com.hk/products_image/3376-Ramonet-ChassagneMontrachetBlanc.jpg",
"imageUrls": [
"http://winebuff.com.hk/products_image/3376-Ramonet-ChassagneMontrachetBlanc.jpg",
"http://media.riepenau.com/wines/17973_b.jpg",
"http://lorempixel.com/400/400/food/3"
],
"properties": [{
"description": "Kırmızı Şaraplar Desc"
}, {
"region": "Bordeaux"
}, {
"age": "16"
}, {
"producer": "Kayra"
}, {
"grapeType": "Espadeiro"
}
],
"priceGlass": "1",
"priceBottle": "2",
"year": "1999"
},
{
"id": 2,
"title": "Montrachet2",
"imageUrl": "http://winebuff.com.hk/products_image/3376-Ramonet-ChassagneMontrachetBlanc.jpg",
"imageUrls": [
"http://winebuff.com.hk/products_image/3376-Ramonet-ChassagneMontrachetBlanc.jpg",
"http://media.riepenau.com/wines/17973_b.jpg",
"http://lorempixel.com/400/400/food/3"
],
"properties": [{
"description": "Kırmızı Şaraplar Desc"
}, {
"region": "Bordeaux"
}, {
"age": "16"
}, {
"producer": "Kayra"
}, {
"grapeType": "Chardonnay"
}
],
"priceGlass": "1",
"priceBottle": "2",
"year": "1999",
}
]
};
var result = _.chain(obj.items).pluck('properties').map(function(obj) {
return _.filter(obj, function(prop) {
return prop.grapeType;
})[0].grapeType;
}).uniq().value();
document.write(JSON.stringify(result));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.8.0/lodash.js"></script>
UPD. If grapeType can be missing from properties then the script should be
var result = _.chain(obj.items).pluck('properties').map(function(obj) {
return (_.filter(obj, function(prop) {
return prop.grapeType;
})[0] || {}).grapeType;
}).compact().uniq().value();
Here's one way to do it with lodash:
_(items)
.pluck('properties')
.map(function(item) {
return _.find(item, _.ary(_.partialRight(_.has, 'grapeType'), 1));
})
.pluck('grapeType')
.uniq()
.value();
First, you get the properties arrays using pluck(). Next, you use find() to get the first object in this array that has a grapeType property. This is done using has(), and partially-applying the argument to build the callback function.
Next, you use pluck() again to get the actual property values. Finally, uniq() ensures there are no duplicates.

Resources