How to remove substring of value of a specific field in mongodb? - mongodb

I have the following mongo document:
{ Name: Peter,
Email: peter#mail.com,
EmailSuffix: peter#mail.com
}
I want to remove the substring before "#" of "EmailSuffix" field in all documents of the collection, so that the result will be:
{ Name: Peter,
Email: peter#mail.com,
EmailSuffix: #mail.com
}
I have tried the following:
db.collection.aggregate( [
{
$match: { EmailSuffix: { $regex: /.+?(?=#)/ } }
},
{
$addFields: {
EmailSuffix: { $split: [ "$EmailSuffix", "?" ] }
}
}
] ).forEach( doc => db.collection.updateMany( { _id: doc._id }, { $set: { EmailSuffix: doc.EmailSuffix[0] } } )`
But it doesn't run.

Use $indexOfCP to locate the first #. Then use $substrCP to do usual substring extraction.
db.collection.update({},
[
{
"$addFields": {
"EmailSuffix": {
"$substrCP": [
"$EmailSuffix",
{
"$indexOfCP": [
"$EmailSuffix",
"#"
]
},
{
"$strLenCP": "$EmailSuffix"
}
]
}
}
}
],
{
multi: true
})
Mongo Playground

Related

How do I capitalize the first letter of a string in mongoDB?

I have the following document in my MongoDB:
{
name: "BRIAN"
}
I'm trying to change it to this format:
{
name: "Brian"
}
I've tried the following:
{
$project: {
name: { $concat: [ { $toLower: '$name' } ]}
}
}
So this makes the string lowercase, then I just need to make the first letter uppercase. Is it possible to do that within the same project aggregation?
As #Wernfried Domscheit suggested, you can use $substrCP to segment name and perform $toLower separately for the "tail" and keep the first character upper case. Use $concat to put back the 2 results together.
db.collection.update({},
[
{
"$addFields": {
"name": {
"$concat": [
{
"$substrCP": [
"$name",
0,
1
]
},
{
"$toLower": {
"$substrCP": [
"$name",
1,
{
"$strLenCP": "$name"
}
]
}
}
]
}
}
}
],
{
multi: true
})
Mongo Playground

How to update a subfield element from another subfield element in mongodb?

Image this data structure :
{
_id: 1
...
sections: [
{
Title: 'hello world',
Title2: '',
},
{
Title: 'goodbye',
Title2: ''
}
]
}
I need to update all Title2 from Title.
I tried things like :
db...update(
{ },
[{ $set:
{
"sections.Title2": "sections.Title",
}
}])
but without success. Also tried with updateMany and some variants like sections.$.Title2.
Thank you for any help
You can do via update + aggregation pipleine(mongod 4.2+) & $map as follow:
db.collection.update({
sections: {
$exists: true
}
},
[
{
$addFields: {
"sections": {
$map: {
input: "$sections",
as: "s",
in: {
"Title": "$$s.Title",
"Title2": "$$s.Title"
}
}
}
}
}
],
{
multi: true
})
Explained:
Find and replace the existing sections with mapped the necessary array values for Title2 to Title.
Add the option {multi:true} to update all documents in collection
playground
Improved version2:
db.collection.update({
sections: {
$exists: true
}
},
[
{
$addFields: {
"sections": {
$map: {
input: "$sections",
as: "s",
in: {
$mergeObjects: [
"$$s",
{
"Title2": "$$s.Title"
}
]
}
}
}
}
}
],
{
multi: true
})
Explained:
In this version you merge the changed value with the subdocument so you dont need to add every of the other fields that are nto going to be changed.
playground2

How match nested fields in mongo by using the match clause?

I am trying to match nested fields in a document in mongo but my query is not working.
Configuration:
[
{
linenumber: "car",
type: "004",
nested: {
info: {
subinfo: "B"
}
},
},
{
linenumber: "car",
type: "005",
nested: {
info: {
subinfo: "G"
}
},
}
]
query:
db.collection.aggregate([
{
$match: {
$and: [
{
linenumber: "car"
},
{
nested: {
info: {
subinfo: {
$in: [
"B",
"G"
]
}
}
}
}
]
}
},
{
$group: {
_id: null,
types: {
$addToSet: "$type"
}
}
}
])
I am using the mongoplayground to test. Here is the link:
https://mongoplayground.net/p/nND59iO1339
I am getting no documents found.
You are almost there. You need to use dot notation.
play
db.collection.aggregate([
{
$match: {
$and: [
{
linenumber: "car"
},
{
"nested.info.subinfo": { //Dot notation
$in: [
"B",
"G"
]
}
}
]
}
},
{
$group: {
_id: null,
types: {
$addToSet: "$type"
}
}
}
])

How to use $addFields in mongo to add elements to just existing documents?

I am trying to add a new field to an existing document by using a combination of both $ifnull and $cond but an empty document is always added at the end.
Configuration:
[
{
line: "car",
number: "1",
category: {
FERRARI: {
color: "blue"
},
LAMBORGHINI: {
color: "red"
}
}
},
{
line: "car",
number: "2",
category: {
FERRARI: {
color: "blue"
}
}
}
]
Query approach:
db.collection.aggregate([
{
$match: {
$and: [
{ line: "car" },
{ number: { $in: ["1", "2"] } }
]
}
},
{
"$addFields": {
"category.LAMBORGHINI.number": {
$cond: [
{ "$ifNull": ["$category.LAMBORGHINI", false] },
"$number",
"$$REMOVE"
]
}
}
},
{
$group: {
_id: null,
CATEGORIES: {
$addToSet: "$category.LAMBORGHINI"
}
}
}
])
Here is the link to the mongo play ground:
https://mongoplayground.net/p/RUnu5BNdnrR
I tried the mentioned query but I still get that ugly empty set added at the end.
$$REMOVE will remove last field/key, from your field category.LAMBORGHINI.number the last field is number that is why it is removing number from the end, you can try another approach,
specify just category.LAMBORGHINI, if condition match then it will return object of current category.LAMBORGHINI and number object after merging using $mergeObjects
{
"$addFields": {
"category.LAMBORGHINI": {
$cond: [
{ "$ifNull": ["$category.LAMBORGHINI", false] },
{
$mergeObjects: [
"$category.LAMBORGHINI",
{ number: "$number" }
]
},
"$$REMOVE"
]
}
}
}
Playground

How to pull array from array in Mongo DB

I have a nested array structured like this
{
"_id": "5dff75968102f11e20ae888e",
"docID": "Employees",
"data": [
[
"234768237",
"Value1",
],
[
"234768238",
"Value2"
],
[
"234768239",
"Value3"
]
]
}
Inside the nested data array, first element is employee ID, Ex: 234768237.
I would want to pass an array of employee ID's and delete the matching ones, for ex : [234768237, 234768238]
What i have tried so far
let employeeIDArray = [234768237, 234768238];
collection.updateOne(
{ docID: "Employees" },
{
$pull: {
"data.$[]": { "0": { $each: employeeIDArray } }
}
}
);
You're close, try:
let employeeIDArray = [234768237, 234768238];
collection.updateOne(
{ docID: "Employees" },
{
$pull: {
"data": { $in: employeeIDArray }
}
}
);
The $each modifier is only available for $push and $addToSet actions, read more about it here.
EDIT:
For Nested Array use $pullAll instead of $pull like so:
collection.updateOne(
{ docID: "Employees" },
{
$pullAll: {
"data.$[]": employeeIDArray
}
});
If you are using MongoDB's latest version then you can use below query to update using aggregation pipeline:
collection.updateOne(
{ docId: "Employees" },
[ {
$set: {
data: {
$filter: {
input: "$data",
cond: { $in: [ { $arrayElemAt: [ "$$this", 0 ] }, [ "234768237", "234768238" ] ] } }
}
}
} ],
{ upsert: true }
)