{
"id": "1234",
"applicant": [
{
"phone": [
{
"prirotynumber": "1",
"areacode": "407",
"linenumber": "1234",
"exchangenumber": "7899"
},
{
"prirotynumber": "27",
"areacode": "407",
"linenumber": "1234",
"exchangenumber": "79999"
}
]
}
]
}
for this id=1234 i need to fetch homephonenuber as applicant.phone.areacode+applicant.phone+linenumber+ applicant.phone+exchangenumber if prirotynumber=1
and
cellphone as applicant.phone.areacode+applicant.phone+linenumber+ applicant.phone+exchangenumber if prirotynumber=27
Expected result here:
{
"key":"value"
}
If this isn't what you need, make your expected result more clarify with right sample data.
db.collection.aggregate([
{
"$match": {
"id": "1234",
"applicant.phone.prirotynumber": "1"
}
},
{
"$unwind": "$applicant"
},
{
"$unwind": "$applicant.phone"
},
{
"$match": {
"applicant.phone.prirotynumber": "1"
}
},
{
"$set": {
"homePhoneNumber ": {
$concat: [
"$applicant.phone.areacode",
"-",
"$applicant.phone.linenumber",
"-",
"$applicant.phone.exchangenumber"
]
}
}
}
])
mongoplayground
Related
Here is the collection:
db.employees.insertMany([
{
"data": {
"category": [
{
"name": "HELLO",
"subcategory": [
"EDUCATION",
"ART",
]
},
{
"name": "HELLO",
"subcategory": [
"GG",
"ART",
]
},
{
"name": "HELLO",
"subcategory": [
"EDUCATION",
"SHORE",
]
}
]
}
},
{
"data": {
"category": [
{
"name": "HELLO",
"subcategory": [
"EDUCATION",
"HELLO",
]
}
]
}
},
{
"data": {
"category": [
{
"name": "HELLO",
"subcategory": [
"GG",
"ART",
]
}
]
}
}
]);
What I want is to locate the elements in 'category' with a 'subcategory' that contains 'EDUCATION' and replace 'EDUCATION' with another string, let's say 'SPORTS'.
I tried a couple of commands but nothing really did the job:
db.employees.updateMany({
"data.category.subcategory": "EDUCATION"
},
{
"$set": {
"data.category.$": {
"subcategory": "SPORTS"
}
}
})
What I saw is that it doesn't update the element by replacing it and it doesn't replace every element that meets the criteria.
Think that MongoDB Update with Aggregation Pipeline fulfills your scenario.
$set - Set data.category value.
1.1. $map - Iterate each element in data.category and return an array.
1.1.1. $mergeObjects - Merge the current document with the document with subcategory field from 1.1.1.1.
1.1.1.1 $map - Iterate each value from the subcategory array. With $cond to replace the word EDUCATION with SPORTS if fulfilled, else use existing value ($$this).
db.employees.updateMany({
"data.category.subcategory": "EDUCATION"
},
[
{
"$set": {
"data.category": {
$map: {
input: "$data.category",
in: {
$mergeObjects: [
"$$this",
{
subcategory: {
$map: {
input: "$$this.subcategory",
in: {
$cond: {
if: {
$eq: [
"$$this",
"EDUCATION"
]
},
then: "SPORTS",
else: "$$this"
}
}
}
}
}
]
}
}
}
}
}
]
Sample Mongo Playground
Here's another way to do it using "arrayFilters".
db.collection.update({
"data.category.subcategory": "EDUCATION"
},
{
"$set": {
"data.category.$[].subcategory.$[elem]": "SPORTS"
}
},
{
"arrayFilters": [
{ "elem": "EDUCATION" }
],
"multi": true
})
Try it on mongoplayground.net.
I want to use this mongoDB collection:
[
{
"_id": {
"$oid": "627c4eb87e7c2b8ba510ac4c"
},
"Contact": [
{
"name": "ABC",
"phone": 5501234,
"mail": "abc#mail.com"
},
{
"name": "DEF",
"phone": 6001234,
"mail": "def#mail.com"
}
],
"nomatter": "trash"
}
]
search for {"name":"ABC"} and return only {"mail":"abc#mail.com"}.
It's possible to use find or it's necessary to use aggregate?
Try this one:
db.collection.aggregate([
{ $match: { "Contact.name": "ABC" } },
{
$project: {
Contact: {
$filter: {
input: "$Contact",
cond: { $eq: [ "$$this.name", "ABC" ] }
}
}
}
},
{ "$replaceWith": { mail: { $first: "$Contact.mail" } } }
])
Mongo Playground
{
"_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.
Suppose I have the following collection.
[
{
"items": {
"item": [
{
"#pid": "131",
"text": "Apple"
},
{
"#pid": "61",
"text": "Mango"
},
{
"#pid": "92",
"text": "cherry"
},
{
"#pid": "27",
"text": "grape"
},
{
"#pid": "34",
"text": "dragonfruit"
}
]
},
"type": "A"
},
{
"items": {
"item": [
{
"#pid": "131",
"text": "Apple"
},
{
"#pid": "27",
"text": "grape"
},
{
"#pid": "34",
"text": "dragonfruit"
}
]
},
"type": "B"
},
{
"items": {
"item": [
{
"#pid": "131",
"text": "Apple"
}
]
},
"type": "A"
}
]
I want to get the type in which apple or mango is sold, group by item name. For the above collection, the output would be :
{
"_id": "Apple",
"items" : [
"A",
"B",
"A"
]
},
{
"_id": "Mango",
"items" : [
"A"
]
}
I tried the following query but it return nothing :
db.collection.aggregate([
{
$match : {
'items.item.text' : {$regex : 'Apple|Mango'}
}
},
{
$project : {
type : "$type"
}
},
{
$group : {
_id : '$items.item',
types : {$push : '$type'}
}
}
])
I think that even if this works, it's going to group by the entire 'items.item'. Where am I going wrong?
P.S. : I don't have the liberty to change the format of the document
Thanks a lot in advance.
You were on the right direction. You need to use $unwind operator and you don't need $project stage in your aggregation. The below query will be helpful:
db.collection.aggregate([
{
$unwind: "$items.item"
},
{
$match: {
"items.item.text": {
$regex: "Apple|Mango"
}
}
},
{
$group: {
_id: "$items.item.text",
type: {
$push: "$type"
}
}
}
])
MongoPlayGroundLink
let's say I have docs such as
{
"nickname": "my nickname",
"comments": [
{
"id": 1
},
{
"id": 1
}
]
}
how do I update it to look like
{
"nickname": "my nickname",
"comments": [
{
"id": 1,
"nickname": "my nickname"
},
{
"id": 1,
"nickname": "my nickname"
}
]
}
This does not seem to be working
db.getCollection('users').update(
{
"comments.nickname": null
},
{ "$set": { "comments.$.nickname": "$nickname" } });
This is just an example to represent my problem.
I would not like to hear about re-structuring and optimizing the fields.
Thanks!
Try this (v4.2):
db.users.updateMany(
{"comments.nickname":null},
[
{"$set": {"comments.nickname": "$nickname"}}
]
)
Note: It will override if any comments.nickname already exists
db.users.aggregate([
{
$match: {
"comments.nickname": null
}
},
{
$addFields: {
comments: {
$map: {
input: "$comments",
in: {
id: "$$this.id",
nickname: {
$cond: [
"$$this.nickname",
"$$this.nickname",
"$nickname"
]
}
}
}
}
}
},
{
$out: "users"
}
])
Note: It will keep already existing values