2016-11-17 1 views
1

が、我々はタイトル(または正しい場合)内のすべての一貫性を保つためにしたい例えばのMongoDB - その説明のための に入ったときに適切な/タイトルケースへのアップデートテキスト

Desc = 
'THE CAT" 
or 
"The Dog" 
or 
"the cow" 

さまざまなテキストケース付き文書の大規模なコレクションを持っています各単語の最初の文字は上、残りは小文字です。

"The Cat", "The Dog", "The Cow" 

データチームは現在やっているようではなく、手動よりも、大量にそれを行うために、更新クエリを作成する際に援助を探しています。

おかげ

+0

どのくらいのドキュメントですか?それほど多くない場合、単純なforEachとplain jsコードを使用することができます。 –

答えて

2

は、以下のタイトルケースを変更するためのアルゴリズムは、Array.prototype.map()方法及び交換によって置換パターンの一部またはすべてのマッチを持つ新しい文字列を返すString.prototype.replace()方法を使用します。 あなたの場合、replace()メソッドのパターンはStringになり、新しい置換えに置き換えられ、逐語的な文字列として扱われます。

まず、map()メソッドを適用する前に、文字列を小文字にして分割する必要があります。変換を実装する関数を定義したら、コレクションを反復してこの関数で更新を適用する必要があります。ループを行うには、ループの中にあなたがしてupdateOne()方法を使用して、各ドキュメントの更新を実行することができますfind()によって返されたカーソル上のcursor.forEach()メソッドを使用します。

は比較的小さなデータセットの場合は、全体の動作を更新するためのBulk() APIを使用しての利点を取る、特に巨大なデータセットを扱うパフォーマンスを向上させるため、以下の

function titleCase(str) { 
    return str.toLowerCase().split(' ').map(function(word) { 
     return word.replace(word[0], word[0].toUpperCase()); 
    }).join(' '); 
} 

db.collection.find({}).foEach(function(doc){ 
    db.collection.updateOne(
     { "_id": doc._id }, 
     { "$set": { "desc": titleCase(doc.desc) } } 
    ); 
}); 

で記述することができますバッチでサーバーに操作を送信するときに、効率的に一括して収集することができます(たとえば、バッチサイズは500)。これにより、すべてのリクエストをサーバーに送信するのではなく、500リクエストごとに1回だけ送信するので、更新をより効率的かつ迅速に行うので、パフォーマンスが大幅に向上します。

次に、このアプローチを示し、最初の例では、MongoDBのバージョン> = 2.6及び< 3.2で利用可能Bulk() APIを使用します。上記の関数を使用して、descフィールドのタイトルを変換することによって、コレクション内のすべてのドキュメントを更新します。

MongoDBのバージョン> = 2.6及び< 3.2

function titleCase(str) { 
    return str.toLowerCase().split(' ').map(function(word) { 
     return word.replace(word[0], word[0].toUpperCase()); 
    }).join(' '); 
} 

var bulk = db.collection.initializeUnorderedBulkOp(), 
    counter = 0; 

db.collection.find().forEach(function (doc) {  
    bulk.find({ "_id": doc._id }).updateOne({ 
     "$set": { "desc": titleCase(doc.desc) } 
    }); 

    counter++; 
    if (counter % 500 === 0) { 
     // Execute per 500 operations 
     bulk.execute(); 
     // re-initialize every 500 update statements 
     bulk = db.collection.initializeUnorderedBulkOp(); 
    } 
}) 
// Clean up remaining queue 
if (counter % 500 !== 0) { bulk.execute(); } 

次の例では、deprecatedBulk() APIため有する新しいMongoDBのバージョン3.2に適用され、を用いたAPIの新しいセットを提供bulkWrite()

MongoDBバージョン3。2以上

var ops = [], 
    titleCase = function(str) { 
     return str.toLowerCase().split(' ').map(function(word) { 
      return word.replace(word[0], word[0].toUpperCase()); 
     }).join(' '); 
    }; 

db.Books.find({ 
    "title": { 
     "$exists": true, 
     "$type": 2 
    } 
}).forEach(function(doc) { 
    ops.push({ 
     "updateOne": { 
      "filter": { "_id": doc._id }, 
      "update": { 
       "$set": { "title": titleCase(doc.title) } 
      } 
     } 
    }); 

    if (ops.length === 500) { 
     db.Books.bulkWrite(ops); 
     ops = []; 
    } 
}) 

if (ops.length > 0) 
    db.Books.bulkWrite(ops); 
+0

Chridamありがとうございます。 試しましたが、何かが欠落している必要があります。私はMongoDbを利用しています。3.2.10 マイコレクションの名前は "Books"なので、 "collection"をスクリプトの "Books"に置き換えました。 MongChefを使用 は、Inellishellにスクリプトを貼り付けて実行し、取得: 2016-11-18T09:46:57.730 + 0000 E QUERY [スレッド1]はTypeError:STRが未定義: タイトルケース@(シェル):3:1 を@(シェル):6:20 [email protected]/mongo/shell/query.js:488:1 @(シェル):1:1 2016-11-18T09:46:57.736 + 0000 E QUERY [スレッド1] SyntaxError:期待される表現、スクリプトの終わり@(シェル):1:19 – MarkM

+0

途中でどのコードを使用しましたか?また、ドキュメント内に '' desc ''フィールドがあることを確認するか、コード内の' 'desc''インスタンスをスキーマの実際の** description **フィールドに置き換えてください。 – chridam

+0

あなたのポストの下のコードを3.2のために使用しました はい、私のdBのフィールド名である2つのスポットで "desc"フィールドを "title"に変更しました。 申し訳ありません。 TypeError:word [0]は定義されていません – MarkM

関連する問題