14

mongo コレクションに次のようなドキュメントが 1 つあるとします。

{
    "_id": 123,
    "field_to_prune": 
    {
        "keep_field_1": "some value",
        "random_field_1": "some value",
        "keep_field_2": "some value",
        "random_field_2": "some value",
        "random_field_3": "some value"
    }
}

そのドキュメントを次のように整理したいと思います。

{
    "_id": 123,
    "field_to_prune": 
    {
        "keep_field_1": "some value",
        "keep_field_2": "some value"
    }
}

ただし、私の問題は、「ランダムな」フィールド名が何であるかがわからないことです。mongo では、いくつかの既知のフィールドを除くすべてのフィールドを $unset するにはどうすればよいですか?

いくつかの方法を考えることができますが、構文はわかりません..すべてのフィールド名を選択し、それらのそれぞれについてフィールドの設定を解除できます。このようなもの:

[Some query to find all field names under "field_to_prune" for id 123].forEach(function(i) { 
    var key = "field_to_prune." + i;
    print("removing field: " + key);
    var mod = {"$unset": {}};
    mod["$unset"][key] = "";

    db.myCollection.update({ _id: "123" }, mod);
});

私が考えていた別の方法は、フィールド名が定義した文字列の配列にない場所を設定解除することでした。それを行う方法もわかりません。何か案は?

4

5 に答える 5

2

実際にこれを行う最善の方法は、カーソルを反復処理し、$unset更新操作を使用して、保持したい既知のフィールドを除くサブドキュメント内のフィールドを削除することです。また、最大の効率を得るには、「一括」操作を使用する必要があります。


MongoDB 3.2Bulk()は、および関連するメソッドを非推奨にします。したがって、使用する必要がある場合は、.bulkWrite()

var count = 0;
var wantedField = ["keep_field_1", "keep_field_2"]; 


var requests = [];
var count = 0;
db.myCollection.find().forEach(function(document) { 
    var fieldToPrune = document.field_to_prune; 
    var unsetOp = {};
    for (var key in fieldToPrune) {     
        if ((wantedFields.indexOf(key) === -1) && Object.prototype.hasOwnProperty.call(fieldToPrune, key ) ) {
            unsetOp["field_to_prune."+key] = " ";        
        }
    }
    requests.push({ 
        "updateOne": { 
            "filter": { "_id": document._id }, 
            "update": { "$unset": unsetOp } 
         }
    });         
    count++;    
    if (count % 1000 === 0) {   
        // Execute per 1000 operations and re-init  
        db.myCollection.bulkWrite(requests); 
        requests = []; 
    } 
})

// Clean up queues
db.myCollection.bulkWrite(requests)

MongoDB 2.6 からBulkAPI を使用できます。

var bulk =  db.myCollection.initializeUnorderedBulkOp();
var count = 0;


db.myCollection.find().forEach(function(document) { 
    fieldToPrune = document.field_to_prune; 
    var unsetOp = {}; 
    for (var key in fieldToPrune) {     
        if ((wantedFields.indexOf(key) === -1) && Object.prototype.hasOwnProperty.call(fieldToPrune, key ) ) {  
            unsetOp["field_to_prune."+key] = " ";             
        } 
    } 
    bulk.find({ "_id": document._id }).updateOne( { "$unset": unsetOp } );         
    count++; 
    if (count % 1000 === 0) {
        // Execute per 1000 operations and re-init     
        bulk.execute();     
        bulk =  db.myCollection.initializeUnorderedBulkOp(); 
    } 
})

// Clean up queues
if (count > 0) { 
    bulk.execute(); 
}
于 2016-03-15T18:12:14.210 に答える