I have below schema
{
id: 123,
values:[
{valueId: "12444", name: "asd"},
{valueId: "555", name: "www"},
]
}
i want to convert it into (combine name into single string)
{
id: 123,
values: "asdwww"
}
i have tried below aggregate which puts all name value in an array
$project: {
attributes: {
"$map": {
"input": "$attributes",
"as": "attr",
"in": {
"id": "$$attr.id",
"values": "$$attr.values.name"
}
}
}
},
which makes it into
{
id: 123,
values:[
"asd",
"www"
]
}
i want to have values as single string value as "asd,www" or "asdwww"
You need $reduce instead of $map:
db.collection.aggregate([
{
$project: {
_id: 1,
values: {
$reduce: {
input: "$values",
initialValue: "",
in: { $concat: [ "$$value", "$$this.name" ] }
}
}
}
}
])
Mongo Playground
Here's an example which shows how to handle delimiters
Related
If I have this collection
[
{
"_id": "637cbf94b4741277c3b53c6c",
"text": "outter",
"username": "test1",
"address": [
{
"text": "inner",
"username": "test2",
"_id": "637cbf94b4741277c3b53c6e"
}
],
"__v": 0
}
]
and would like to search for the nested document by _id and return all of the nested document. If I do
db.collection.find({
_id: "637cbf94b4741277c3b53c6c"
},
{
address: {
$eq: {
_id: "637cbf94b4741277c3b53c6e"
}
}
})
I get
query failed: (Location16020) Expression $eq takes exactly 2 arguments. 1 were passed in.
Playground link
Question
Can anyone see what I am doing wrong?
use $elemMatch and also you have extra unneeded brackets. try
db.collection.find({
_id: "637cbf94b4741277c3b53c6c",
address: {
$elemMatch: {
_id: "637cbf94b4741277c3b53c6e"
}
}
})
Edit: if you only want to return the address add projection like this
db.collection.find({
_id: "637cbf94b4741277c3b53c6c",
address: {
$elemMatch: {
_id: "637cbf94b4741277c3b53c6e"
}
}
},
{
_id: 0,
address: 1
})
One option is to use find:
db.collection.find({},
{
_id: 0,
address: {
$elemMatch: {
_id: "637cbf94b4741277c3b53c6e"
}
}
})
See how it works on the playground example
The other option is to use aggregation pipeline:
db.collection.aggregate([
{
$match: {
$expr: {
$in: [
"637cbf94b4741277c3b53c62",
"$address._id"
]
}
}
},
{
$replaceRoot: {
newRoot: {
$first: {
$filter: {
input: "$address",
cond: {
$eq: [
"$$this._id",
"637cbf94b4741277c3b53c6e"
]
}
}
}
}
}
}
])
See how it works on the playground example
I want to return an array, which is a property inside my mongo model/document, and I want that array to be sorted.
My MongoDB document looks like:
_id: ObjectID("6248e49c88ff07aedee8c000")
title: "School"
items: [
{
sort: 2,
name: "homework"
},
{
sort: 1,
name: "exam"
},
{
sort: 3,
name: "essay"
},
]
And I'm trying to return:
items: [
{
sort: 1,
name: "exam"
},
{
sort: 2,
name: "homework"
},
{
sort: 3,
name: "essay"
}
]
I have tried aggregation:
app.get("/api/v1/lists/:id", async (req,res) =>{
List.aggregate([{
"$match" :{"_id": req.params.id}
},{
"$unwind" : "$items"
} , {
"$sort" : {"sort": 1}
}
], (err, items)=>{
res.json(items)
})
}
Mongo Playground reference
Since $unwind returns the arrays as objects, we are using the $group to push the objects back into the items array
db.collection.aggregate([
{
$unwind: "$items"
},
{
$sort: {
"items.sort": 1
}
},
{
$group: {
_id: "$_id",
items: {
$push: "$items"
}
}
},
])
Output -
[
{
"_id": 1.212112e+06,
"items": [
{
"name": "exam",
"sort": 1
},
{
"name": "homework",
"sort": 2
},
{
"name": "essay",
"sort": 3
}
]
}
]
Structure:
[
{
"_id": "12",
"title": "Vanella Icream",
"contain":"sugar",
"details": [
{
"flavour": "Vanella"
},
{
"weight": "6KG"
}
]
},
{
"_id": "3",
"title": "Pretzels",
"contain":"salt",
"details": [
{
"flavour": "Wheat"
},
{
"weight": "2KG"
}
]
}
]
Expected Output
details:
{
"flavour": [
"Vanella",
"Wheat",
],
"weight": [
"6KG",
"2KG",
]
}
More Important: I've to do this without details.flavour or details.weight.
I’ve tried with $addToSet, $filter $group but I’m not getting results like that. anyone please suggest.
Mongo Playground: https://mongoplayground.net/p/SXw3jaRDzLy
$project to show required field
$unwind deconstruct the details array
$objectToArray convert details object to array key-value format
$unwind deconstruct the details array
$group by details key and construct the array of values
$group by null and construct the array of details in key-value format
$arrayToObject convert above result from key-value format array of object to an object
db.collection.aggregate([
{
$project: {
_id: 0,
details: 1
}
},
{ $unwind: "$details" },
{
$project: {
details: { $objectToArray: "$details" }
}
},
{ $unwind: "$details" },
{
$group: {
_id: "$details.k",
v: { $addToSet: "$details.v" }
}
},
{
$group: {
_id: null,
details: {
$push: { k: "$_id", v: "$v" }
}
}
},
{
$project: {
_id: 0,
details: { $arrayToObject: "$details" }
}
}
])
Playground
I have the following object in the format _id: userID and a Mongoose query:
const obj = {
111: "222",
333: "444",
555: "666"
};
Model.aggregate([
{
$addFields: {
userID: ???
}
}
]);
I need a way to add a userID field to each document based on the object. So let's say the collection has this data:
[
{
_id: "111",
...
},
{
_id: "333",
...
},
{
_id: "555",
...
}
]
The document should end up looking like this:
[
{
_id: "111",
userID: "222",
...
},
{
_id: "333",
userID: "444",
...
},
{
_id: "555",
userID: "666",
...
}
]
How can I do this?
You need to start with $objectToArray to get your dynamic object as an array of keys and values. Then you can use $filter to find matching pair, $arrayElemAt to get single element:
db.collection.aggregate([
{
$addFields: {
userId: {
$let: {
vars: {
match: {
$arrayElemAt: [
{
$filter: {
input: { $objectToArray: { 111: "222", 333: "444", 555: "666" } },
cond: { $eq: [ "$$this.k", { $toString: "$_id" } ] }
}
},
0
]
}
},
in: "$$match.v"
}
}
}
}
])
Mongo Playground
I have an array of data returned by MongoDB. I would like to know how to join first name and last name from the below array using mongodb aggregation framework.
i have seen couple of posts similer to my query,however i did not understand the answer and hence i am posting a new question.
I have written a sample code.any helping corrcting my code would be really appreciated
var playersData = [
{
firstName: 'David',
LastName: 'John',
country: 'India'
},
{
firstName: 'Chris',
LastName: 'Jericho',
country: 'USA'
},
{
firstName: 'John',
LastName: 'Cena',
country: 'USA'
}
];
code
playerModel.aggregate([
{
"$match": {
[{ "country": 'USA' }]
}
},
{
"$project": {
"_id": 0, "playersData.firstName": 1, "playersData.lastName": 1,
fullName: {
$reduce: {
input: '$playersData',
initialValue: '',
in: {
$concat: ["$$value", "$$this"]
}
}
}
}
}
], function (err, result) {
})
You can try below aggregation.
$match to keep player array where at least one of the country is USA followed by $filter to filter elements with country as USA and $map with $concat to join the first name and last name to produce the full name array.
playerModel.aggregate([
{
"$match": {
"playersData.country": "USA"
}
},
{
"$project": {
"_id": 0,
"playersData.firstName": 1,
"playersData.lastName": 1,
"fullname": {
"$map": {
"input": {
"$filter": {
"input": "$playersData",
"as": "playerf",
"cond": {
"$eq": [
"$$playerf.country", "USA"
]
}
}
},
"as": "playerm",
"in": {
"$concat": [
"$$playerm.firstName",
",",
"$$playerm.lastName"
]
}
}
}
}
}
])