I have collection with documents like this one:
{
"_id": 1,
"people": [
{
"name": "Bob",
"age": "15"
},
{
"name": "Alice",
"age": "18"
}
]
}
My query is:
db.groups.aggregate({ $match: { "_id": 1 }}, { $project: { "_id": 0, "people.name": 1 } })
This query returns:
{
"people": [
{
"name": "Bob"
},
{
"name": "Alice"
}
]
}
But I need the result like:
{ "names": [ "Bob", "Alice" ] }
Which parameters should I add to the .aggregate() function?
The solution is:
db.groups.aggregate({ $match: { "_id": 1 }}, { $project: { "_id": 0, "names": "$people.name" } })
Related
I have this simple collection of students:
{
"_id": "btv7865reVGlksabv",
"students": [
{
"name": "John",
"age": 30
},
{
"name": "Henry",
"age": 25
}
]
}
Now I want to push new students into this array:
const newStudents = [
{
"name": "Mike",
"age": 22
},
{
"name": "Kim",
"age": 20
}
]
What I tried so far is:
Students.update(
{
"_id": "btv7865reVGlksabv"
},
{
$push: {
"students": newStudents
}
}
);
The above query doesn't update my collection for some reason. Can anyone help me correct this query?
Chain up $push with $each
db.collection.update({
"_id": "btv7865reVGlksabv"
},
{
$push: {
"students": {
$each: [
{
"name": "Mike",
"age": 22
},
{
"name": "Kim",
"age": 20
}
]
}
}
})
Mongo Playground
Maybe something like this:
db.collection.update({},
[
{
$addFields: {
students: {
$concatArrays: [
"$students",
[
{
name: "New1",
age: "New1"
},
{
name: "New2",
age: "New2"
}
]
]
}
}
}
])
Explained:
Use $addFileds->$concatArrays to update via aggregation pipeline ( 4.2+) to add the elements from your new array to the already existing array ...
Playground
How can I push value into multiple nested array with specific conditions? I have a document like this
[
{
"_id": "class_a",
"students": [
{
"_id": "1a",
"name": "John",
"grades": []
},
{
"_id": "1b",
"name": "Katie",
"grades": []
},
{
"_id": "1c",
"name": "Andy",
"grades": []
},
]
}
]
Query to insert into nested array. (Not sure what is missing here)
db.collection.update({
"_id": "class_a",
"students": {
$elemMatch: {
"_id": {
"$in": [
"1a",
"1b"
]
}
}
}
},
{
$push: {
"students.$.grades": "A+"
}
})
Got the following result. But I was expecting both John and Katie have A+ in grades
[
{
"_id": "class_a",
"students": [
{
"_id": "1a",
"grades": ["A+"],
"name": "John"
},
{
"_id": "1b",
"grades": [],
"name": "Katie"
},
{
"_id": "1c",
"grades": [],
"name": "Andy"
}
]
}
]
Expected result
[
{
"_id": "class_a",
"students": [
{
"_id": "1a",
"grades": ["A+"],
"name": "John"
},
{
"_id": "1b",
"grades": ["A+"],
"name": "Katie"
},
{
"_id": "1c",
"grades": [],
"name": "Andy"
}
]
}
]
Mongo playground to test the code
You can use $[<identifier>] to update only the items that match a condition. Your first {} is to find the relevant documents, while the arrayFilters is to find the relevant items inside the document nested array:
db.collection.update(
{_id: "class_a", students: {$elemMatch: {_id: {$in: ["1a", "1b"]}}}},
{$push: {"students.$[item].grades": "A+"}},
{arrayFilters: [{"item._id": {$in: ["1a", "1b"]}}], upsert: true}
)
See how it works on the playground example
You should really use arrayFilters for these otherwse it'll only match the first entity. You don't need to use $elemMatch at all.
Playground - https://mongoplayground.net/p/_7y89KB83Ho
db.collection.update({
"_id": "class_a"
},
{
$push: {
"students.$[students].grades": "A+"
}
},
{
"arrayFilters": [
{
"students._id": {
"$in": [
"1a",
"1b"
]
}
}
]
})
{
"_id" : ObjectId("52f504bb2f9dd91186211537"),
"Data": {
"Stage": {
"FirstArray": [
{
"Name": "FirstLevelArray-FirstObject",
"_id": ObjectId("5fe1a5fa2d8e360ac4093b7e"),
"SecondArray": [
{
"Name": "1-SecondLevelArray-FirstObject",
"_id": ObjectId("5fe1a7a52d8e360ac4093b81")
},
{
"Name": "1-SecondLevelArray-SecondObject",
"_id": ObjectId("5fe1a7a52d8e360ac4093b82")
}
]
},
{
"Name": "FirstLevelArray-SecondObject",
"_id": ObjectId("5fdc9dced45fa417d417c441"),
"SecondArray": [
{
"Name": "2-SecondLevelArray-FirstObject",
"_id": ObjectId("5fde08564d28f313acc0c93b")
},
{
"Name": "2-SecondLevelArray-SecondObject",
"_id": ObjectId("5fde08d64d28f313acc0c93c")
}
]
}
]
}
}
}
This is the sample format of my code.
I want to delete this object { "Name": "2-SecondLevelArray-SecondObject", "_id": ObjectId("5fde08d64d28f313acc0c93c") } from this record.
I tried this query
model.update(
{ $and: [{ "_id": ObjectId("52f504bb2f9dd91186211537") }},
{"Data.Stage.FirstArray.SecondArray._id":ObjectId("5fde08d64d28f313acc0c93c")}] ,
{ $pull:{
"Data.Stage.FirstArray.$.SecondArray._id": ObjectId("5fe1a7a52d8e360ac4093b82")
}
},
{new:true,upsert:false})
How would I achieve this in MongoDB ?
Here is the expected result of find({"_id" : ObjectId("52f504bb2f9dd91186211537")}) after the update
EDIT: {
"_id" : ObjectId("52f504bb2f9dd91186211537"),
"Data": {
"Stage": {
"FirstArray": [
{
"Name": "FirstLevelArray-FirstObject",
"_id": ObjectId("5fe1a5fa2d8e360ac4093b7e"),
"SecondArray": [
{
"Name": "1-SecondLevelArray-FirstObject",
"_id": ObjectId("5fe1a7a52d8e360ac4093b81")
},
{
"Name": "1-SecondLevelArray-SecondObject",
"_id": ObjectId("5fe1a7a52d8e360ac4093b82")
}
]
},
{
"Name": "FirstLevelArray-SecondObject",
"_id": ObjectId("5fdc9dced45fa417d417c441"),
"SecondArray": [
{
"Name": "2-SecondLevelArray-FirstObject",
"_id": ObjectId("5fde08564d28f313acc0c93b")
}
]
}
]
}
}
}
model.update({ _id: ObjectId("52f504bb2f9dd91186211537"), Data.Stage.FirstArray:{ $elemMatch: { SecondArray:{$elemMatch:{"_id":ObjectId("5fde08d64d28f313acc0c93c")}}}}},
{ $pull:{ "Data.Stage.FirstArray.$.SecondArray":{"_id": ObjectId("5fde08d64d28f313acc0c93c") }}},{new:true,upsert:false})
My idea is to filter out those with your given Name field
model.updateMany({}, {
$set: { "Data.Stage.FirstArray.SecondArray": { $filter: {
input: "$Data.Stage.FirstArray.SecondArray",
as: "item",
cond: { $eq: [ "$$item.Name", '2-SecondLevelArray-SecondObject' ] }
} } },
});
Honestly, I'm not sure it will be working but it worths a try.
I am struggling to find some examples of using the mongo aggregation framework to process documents which has an array of items where each item also has an array of other obejects (array containing an array)
In the example document below what I would really like is an example that sums the itemValue in the results array of all cases in the document and accross the collection where the result.decision was 'accepted'and group by the document locationCode
However, even an example that found all documents where the result.decision was 'accepted' to show or that summmed the itemValue for the same would help
Many thanks
{
"_id": "333212",
"data": {
"locationCode": "UK-555-5566",
"mode": "retail",
"caseHandler": "A N Other",
"cases": [{
"caseId": "CSE525666",
"items": [{
"id": "333212-CSE525666-1",
"type": "hardware",
"subType": "print cartridge",
"targetDate": "2020-06-15",
"itemDetail": {
"description": "acme print cartridge",
"quantity": 2,
"weight": "1.5"
},
"result": {
"decision": "rejected",
"decisionDate": "2019-02-02"
},
"isPriority": true
},
{
"id": "333212-CSE525666-2",
"type": "Stationery",
"subType": "other",
"targetDate": "2020-06-15",
"itemDetail": {
"description": "staples box",
"quantity": 3,
"weight": "1.66"
},
"result": {
"decision": "accepted",
"decisionDate": "2020-03-03",
"itemValue": "23.01"
},
"isPriority": true
}
]
},
{
"caseId": "CSE885655",
"items": [{
"id": "333212-CSE885655-1",
"type": "marine goods",
"subType": "fish food",
"targetDate": "2020-06-04",
"itemDetail": {
"description": "fish bait",
"quantity": 5,
"weight": "0.65"
},
"result": {
"decision": "accepted",
"decisionDate": "2020-03-02"
},
"isPriority": false
},
{
"id": "333212-CSE885655-4",
"type": "tobacco products",
"subType": "cigarettes",
"deadlineDate": "2020-06-15",
"itemDetail": {
"description": "rolling tobbaco",
"quantity": 42,
"weight": "2.25"
},
"result": {
"decision": "accepted",
"decisionDate": "2020-02-02",
"itemValue": "48.15"
},
"isPriority": true
}
]
}
]
},
"state": "open"
}
You're probably looking for $unwind. It takes an array within a document and creates a separate document for each array member.
{ foos: [1, 2] } -> { foos: 1 }, { foos: 2}
With that you can create a flat document structure and match & group as normal.
db.collection.aggregate([
{
$unwind: "$data.cases"
},
{
$unwind: "$data.cases.items"
},
{
$match: {
"data.cases.items.result.decision": "accepted"
}
},
{
$group: {
_id: "$data.locationCode",
value: {
$sum: {
$toDecimal: "$data.cases.items.result.itemValue"
}
}
}
},
{
$project: {
_id: 0,
locationCode: "$_id",
value: "$value"
}
}
])
https://mongoplayground.net/p/Xr2WfFyPZS3
Alternative solution...
We group by data.locationCode and sum all items with this condition:
cases[*].items[*].result.decision" == "accepted"
db.collection.aggregate([
{
$group: {
_id: "$data.locationCode",
itemValue: {
$sum: {
$reduce: {
input: "$data.cases",
initialValue: 0,
in: {
$sum: {
$concatArrays: [
[ "$$value" ],
{
$map: {
input: {
$filter: {
input: "$$this.items",
as: "f",
cond: {
$eq: [ "$$f.result.decision", "accepted" ]
}
}
},
as: "item",
in: {
$toDouble: {
$ifNull: [ "$$item.result.itemValue", 0 ]
}
}
}
}
]
}
}
}
}
}
}
}
])
MongoPlayground
I have a MongoDB document that looks something like this:
{
"_id": 000000000001,
"sample": [
{
"_id": {
"$oid": "12345678910"
},
"Phone": 5555555555,
"LastName": "Musk",
"FirstName": "Elon",
"responses": {
"question1": "hello",
"question2": "world"
}
},
{
"_id": {
"$oid": "12345678911"
},
"Phone": "1111111111",
"LastName": "Jobs",
"FirstName": "Steve",
"responses": {
"question1": "goodbye",
"question2": "world"
}
}
]
}
I want to get a $sum of all the people who have given the response hello to question1 and all the people who have given the response world to question2.
For example. I want a response that looks something like this:
{ 'question1': 1, 'question2': 2 }
My query looks like this, but it isn't working. It's only returning 0 for any given sum when I know that's not the case.
db.collection(collection).aggregate([
{ $match : { } },
{ $group: {
_id: "responses",
"question1": { $sum: { $cond: [ { $eq: [ "$sample.responses.question1", "hello"] }, 1, 0 ] } },
"question2": { $sum: { $cond: [ { $eq: [ "$sample.responses.question2", "world"] }, 1, 0 ] } }
}
}
])
Can anyone help me out?