私はフォームのコレクションにたくさんのmongodbドキュメントを持っています:
{
....
"URL":"www.abc.com/helloWorldt/..."
.....
}
に置き換えhelloWorldt
たいhelloWorld
:
{
....
"URL":"www.abc.com/helloWorld/..."
.....
}
コレクション内のすべてのドキュメントでこれを実現するにはどうすればよいですか?
私はフォームのコレクションにたくさんのmongodbドキュメントを持っています:
{
....
"URL":"www.abc.com/helloWorldt/..."
.....
}
に置き換えhelloWorldt
たいhelloWorld
:
{
....
"URL":"www.abc.com/helloWorld/..."
.....
}
コレクション内のすべてのドキュメントでこれを実現するにはどうすればよいですか?
db.media.find({mediaContainer:"ContainerS3"}).forEach(function(e,i) {
e.url=e.url.replace("//a.n.com","//b.n.com");
db.media.save(e);
});
現在、
Mongo 4.2
、db.collection.updateMany
(のエイリアスdb.collection.update
)は集約パイプラインを受け入れることができ、最終的にはそれ自体の値に基づいてフィールドを更新できます。Mongo 4.4
と、新しい集計演算子$replaceOne
により、文字列の一部を非常に簡単に置き換えることができます。// { 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/ } }
)は一致クエリであり、更新するドキュメント(を含むドキュメント)をフィルタリングし"helloWorldt"
、クエリを高速化するために存在します。$set: { URL: {...
)は、更新集約パイプラインです(集約パイプラインの使用を示す角括弧に注意してください)。
$set
は新しい集計演算子(Mongo 4.2
)であり、この場合はフィールドの値を置き換えます。$replaceOne
演算子を使用して計算されます。URL
自身の値()に基づいて直接変更される方法に注意してください$URL
。Mongo 4.4
開始する前Mongo 4.2
に、適切な文字列$replace
演算子がないため、とのbancalミックスを使用する必要が$concat
あり$split
ます。
db.collection.updateMany(
{ URL: { $regex: "/helloWorldt/" } },
[{
$set: { URL: {
$concat: [
{ $arrayElemAt: [ { $split: [ "$URL", "/helloWorldt/" ] }, 0 ] },
"/helloWorld/",
{ $arrayElemAt: [ { $split: [ "$URL", "/helloWorldt/" ] }, 1 ] }
]
}}
}]
)
現在、フィールドの値を使用して更新することはできません。したがって、ドキュメントを反復処理し、関数を使用して各ドキュメントを更新する必要があります。これを行う方法の例をここに示します。MongoDB:同じドキュメントのデータを使用してドキュメントを更新する
ドキュメント内のすべての部分文字列を置き換えるには、次を使用します。
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);
});
mongodbコレクションは、ネストされた配列/オブジェクトなどで少し複雑になることがあり、その周りにループを構築するのは比較的困難です。私の回避策はちょっと生っぽいですが、コレクションの複雑さに関係なく、ほとんどのシナリオで機能します。
1.mongodumpを使用してコレクションを.bsonにエクスポートします
mongodump --db=<db_name> --collection=<products> --out=data/
2. bsondumpを使用して、.bsonを.json形式に変換します
bsondump --outFile products.json data/<db_name>/products.bson
3. .jsonファイルの文字列をsed(Linuxターミナルの場合)またはその他のツールに置き換えます
sed -i 's/oldstring/newstring/g' products.json
4.インポートする前にコレクションを削除する--dropタグを付けたmongoimportを使用して.jsonコレクションをインポートし直します
mongoimport --db=<db_name> --drop --collection products <products.json
または、mongoimportとmongodumpの両方の接続に--uriを使用することもできます
例
mongodump --uri "mongodb://mongoadmin:mystrongpassword@10.148.0.7:27017,10.148.0.8:27017,10.148.0.9:27017/my-dbs?replicaSet=rs0&authSource=admin" --collection=products --out=data/
nodejs。npmのmongodbパッケージを使用する
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});
});
});
選択した回答(@Naveedの回答)へのコメントのフォーマットがスクランブルされているため、これを回答として追加します。すべてのクレジットはNaveedに送られます。
ただ素晴らしい。私の場合は、配列であるフィールドがあるので、ループを追加する必要がありました。
私の質問は:
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));
})
今、あなたはそれを行うことができます!
Mongoスクリプトを使用して、データをその場で操作できます。わたしにはできる!
このスクリプトを使用して、アドレスデータを修正します。
現在の住所の例:「No.12、FIFTHAVENUE」。
最後の冗長なカンマ、予想される新しいアドレス "" No.12、FIFTHAVENUE"を削除したいと思います。
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);
}
}
お役に立てれば!
Regex
これは、メソッドの最初の部分でを使用して実行でき、その文字列replace
の[すべてg
の正規表現パターン]オカレンスを2番目の文字列に置き換えます。これは、Javascriptの場合と同じ正規表現です。例:
const string = "www.abc.com/helloWorldt/...";
console.log(string);
var pattern = new RegExp(/helloWorldt/)
replacedString = string.replace(pattern, "helloWorld");
console.log(replacedString);
正規表現が文字列を置き換えているので、メソッドによって各要素を見つけて反復し、次のようにループforEach
内に1つずつ保存することで、MongoDBシェルを簡単に実行できます。forEach
> 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/" }
>
サブ文字列を検索して別の文字列に置き換える場合は、次のように試すことができます。
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);
}
})