Reputation: 1791
I have a lot of mongodb documents in a collection of the form:
{
....
"URL":"www.abc.com/helloWorldt/..."
.....
}
I want to replace helloWorldt
with helloWorld
to get:
{
....
"URL":"www.abc.com/helloWorld/..."
.....
}
How can I achieve this for all documents in my collection?
Upvotes: 121
Views: 134312
Reputation: 167
db.filetranscoding.updateMany({ profiles: { $regex: /N_/ } },[{$set: { profiles: {$$replaceAll: { input: "$profiles", find:"N_",replacement: "" }},"status":"100"}}])
filetranscoding -- Collection Name
profiles -- ColumnName in which you want to update
/N_/ -- String which you are searching (where Condition )
find:"N_",replacement: "" -- N_ which u want to remove "" from which you want to remove here we are taking blank String
Upvotes: 0
Reputation: 933
If you want to search for a sub string, and replace it with another, you can try like below,
db.collection.find({ "fieldName": /.*stringToBeReplaced.*/ }).forEach(function(e, i){
if (e.fieldName.indexOf('stringToBeReplaced') > -1) {
e.content = e.content.replace('stringToBeReplaced', 'newString');
db.collection.update({ "_id": e._id }, { '$set': { 'fieldName': e.fieldName} }, false, true);
}
})
Upvotes: 2
Reputation: 61774
Nowadays,
Mongo 4.2
, db.collection.updateMany
(alias of db.collection.update
) can accept an aggregation pipeline, finally allowing the update of a field based on its own value.Mongo 4.4
, the new aggregation operator $replaceOne
makes it very easy to replace part of a string.// { URL: "www.abc.com/helloWorldt/..." }
// { URL: "www.abc.com/HelloWo/..." }
db.collection.updateMany(
{ URL: { $regex: /helloWorldt/ } },
[{
$set: { URL: {
$replaceOne: { input: "$URL", find: "helloWorldt", replacement: "helloWorld" }
}}
}]
)
// { URL: "www.abc.com/helloWorld/..." }
// { URL: "www.abc.com/HelloWo/..." }
{ URL: { $regex: /helloWorldt/ } }
) is the match query, filtering which documents to update (the ones containing "helloWorldt"
) and is just there to make the query faster.$set: { URL: {...
) is the update aggregation pipeline (note the squared brackets signifying the use of an aggregation pipeline):
$set
is a new aggregation operator (Mongo 4.2
) which in this case replaces the value of a field.$replaceOne
operator. Note how URL
is modified directly based on the its own value ($URL
).Before Mongo 4.4
and starting Mongo 4.2
, due to the lack of a proper string $replace
operator, we have to use a bancal mix of $concat
and $split
:
db.collection.updateMany(
{ URL: { $regex: "/helloWorldt/" } },
[{
$set: { URL: {
$concat: [
{ $arrayElemAt: [ { $split: [ "$URL", "/helloWorldt/" ] }, 0 ] },
"/helloWorld/",
{ $arrayElemAt: [ { $split: [ "$URL", "/helloWorldt/" ] }, 1 ] }
]
}}
}]
)
Upvotes: 119
Reputation: 3812
This can be done by using the Regex
in the first part of the method replace
and it will replace the [all if g
in regex pattern] occurrence(s) of that string with the second string, this is the same regex as in Javascript e.g:
const string = "www.abc.com/helloWorldt/...";
console.log(string);
var pattern = new RegExp(/helloWorldt/)
replacedString = string.replace(pattern, "helloWorld");
console.log(replacedString);
Since the regex is replacing the string, now we can do this is MongoDB shell easily by finding and iterating with each element by the method forEach
and saving one by one inside the forEach
loop as below:
> db.media.find()
{ "_id" : ObjectId("5e016628a16075c5bd26fbe3"), "URL" : "www.abc.com/helloWorld/" }
{ "_id" : ObjectId("5e016701a16075c5bd26fbe4"), "URL" : "www.abc.com/helloWorldt/" }
>
> db.media.find().forEach(function(o) {o.URL = o.URL.replace(/helloWorldt/, "helloWorld"); printjson(o);db.media.save(o)})
{
"_id" : ObjectId("5e016628a16075c5bd26fbe3"),
"URL" : "www.abc.com/helloWorld/"
}
{
"_id" : ObjectId("5e016701a16075c5bd26fbe4"),
"URL" : "www.abc.com/helloWorld/"
}
> db.media.find()
{ "_id" : ObjectId("5e016628a16075c5bd26fbe3"), "URL" : "www.abc.com/helloWorld/" }
{ "_id" : ObjectId("5e016701a16075c5bd26fbe4"), "URL" : "www.abc.com/helloWorld/" }
>
Upvotes: 2
Reputation: 349
Sometimes the mongodb collections can get little complex with nested arrays/objects etc where it would be relatively difficult to build loops around them. My work around is kinda raw but works in most scenarios regardless of complexity of the collection.
1. Export The collection using mongodump into .bson
mongodump --db=<db_name> --collection=<products> --out=data/
2. Convert .bson into .json format using bsondump
bsondump --outFile products.json data/<db_name>/products.bson
3. Replace the strings in the .json file with sed(for linux terminal) or with any other tools
sed -i 's/oldstring/newstring/g' products.json
4. Import back the .json collection with mongoimport with --drop tag where it would remove the collection before importing
mongoimport --db=<db_name> --drop --collection products <products.json
Alternatively you can use --uri for connections in both mongoimport and mongodump
example
mongodump --uri "mongodb://mongoadmin:[email protected]:27017,10.148.0.8:27017,10.148.0.9:27017/my-dbs?replicaSet=rs0&authSource=admin" --collection=products --out=data/
Upvotes: 11
Reputation: 141
To replace ALL occurrences of the substring in your document use:
db.media.find({mediaContainer:"ContainerS3"}).forEach(function(e,i) {
var find = "//a.n.com";
var re = new RegExp(find, 'g');
e.url=e.url.replace(re,"//b.n.com");
db.media.save(e);
});
Upvotes: 6
Reputation: 744
The formatting of my comment to the selected answer (@Naveed's answer) has got scrambled - so adding this as an answer. All credit goes to Naveed.
Just awesome. My case was - I have a field which is an array - so I had to add an extra loop.
My query is:
db.getCollection("profile").find({"photos": {$ne: "" }}).forEach(function(e,i) {
e.photos.forEach(function(url, j) {
url = url.replace("http://a.com", "https://dev.a.com");
e.photos[j] = url;
});
db.getCollection("profile").save(e);
eval(printjson(e));
})
Upvotes: 4
Reputation: 26423
nodejs. Using mongodb package from npm
db.collection('ABC').find({url: /helloWorldt/}).toArray((err, docs) => {
docs.forEach(doc => {
let URL = doc.URL.replace('helloWorldt', 'helloWorld');
db.collection('ABC').updateOne({_id: doc._id}, {URL});
});
});
Upvotes: 6
Reputation: 2027
db.media.find({mediaContainer:"ContainerS3"}).forEach(function(e,i) {
e.url=e.url.replace("//a.n.com","//b.n.com");
db.media.save(e);
});
Upvotes: 157
Reputation: 77
Now you can do it!
We can use Mongo script to manipulate data on the fly. It works for me!
I use this script to correct my address data.
Example of current address: "No.12, FIFTH AVENUE,".
I want to remove the last redundant comma, the expected new address ""No.12, FIFTH AVENUE".
var cursor = db.myCollection.find().limit(100);
while (cursor.hasNext()) {
var currentDocument = cursor.next();
var address = currentDocument['address'];
var lastPosition = address.length - 1;
var lastChar = address.charAt(lastPosition);
if (lastChar == ",") {
var newAddress = address.slice(0, lastPosition);
currentDocument['address'] = newAddress;
db.localbizs.update({_id: currentDocument._id}, currentDocument);
}
}
Hope this helps!
Upvotes: 2
Reputation: 871
Currently, you can't use the value of a field to update it. So you'll have to iterate through the documents and update each document using a function. There's an example of how you might do that here: MongoDB: Updating documents using data from the same document
Upvotes: 8