Java MongoDB:ドキュメントの更新

Java MongoDB:ドキュメントの更新

このチュートリアルでは、Java MongoDB APIcollection.update()を使用してドキュメントを更新する方法を示します。

テストデータ

次のデータ/ドキュメントが挿入されると仮定します。

{
    "hosting" : "hostA",
    "type" : "vps",
    "clients" : 1000
},
{
    "hosting" : "hostB",
    "type" : "dedicated server",
    "clients" : 100
},
{
    "hosting" : "hostC",
    "type" : "vps",
    "clients" : 900
}
{ "_id" : { "$oid" : "id"} , "hosting" : "hostA" , "type" : "vps" , "clients" : 1000}
{ "_id" : { "$oid" : "id"} , "hosting" : "hostB" , "type" : "dedicated server" , "clients" : 100}
{ "_id" : { "$oid" : "id"} , "hosting" : "hostC" , "type" : "vps" , "clients" : 900}

1. DBCollection.update() with $set

hosting = 'hostB'のドキュメントを検索し、クライアントの値を100から110に更新します。

    BasicDBObject newDocument = new BasicDBObject();
    newDocument.put("clients", 110);

    BasicDBObject searchQuery = new BasicDBObject().append("hosting", "hostB");

    collection.update(searchQuery, newDocument);

出力

{ "_id" : { "$oid" : "id"} , "hosting" : "hostA" , "type" : "vps" , "clients" : 1000}
{ "_id" : { "$oid" : "id"} , "clients" : 110}
{ "_id" : { "$oid" : "id"} , "hosting" : "hostC" , "type" : "vps" , "clients" : 900}

The document is replaced!?
待ってください、「hostB」ドキュメント全体が別の新しいドキュメントに置き換えられます。これは私たちが望んでいることではありません。

特定の値のみを更新するには、$setの更新修飾子を使用します。

    BasicDBObject newDocument = new BasicDBObject();
    newDocument.append("$set", new BasicDBObject().append("clients", 110));

    BasicDBObject searchQuery = new BasicDBObject().append("hosting", "hostB");

    collection.update(searchQuery, newDocument);

出力

{ "_id" : { "$oid" : "id"} , "hosting" : "hostA" , "type" : "vps" , "clients" : 1000}
{ "_id" : { "$oid" : "id"} , "hosting" : "hostB" , "type" : "dedicated server" , "clients" : 110}
{ "_id" : { "$oid" : "id"} , "hosting" : "hostC" , "type" : "vps" , "clients" : 900}

Note
MongoDBチームはDBCollection.replace()という名前の別の新しいAPIを作成する必要があります。多くの初心者がこのDBCollection.update() APIに閉じ込められ、誤ってドキュメント全体を置き換えてしまいます。 繰り返しますが、特定の値を更新するには、$setを使用します。

2. DBCollection.update() with $inc

この例は、特定の値を増やすための$inc修飾子の使用を示しています。 hosting = 'hostB'のドキュメントを検索し、値を100から199、(100 + 99)= 199に増やして、 'clients'値を更新します。

    BasicDBObject newDocument =
        new BasicDBObject().append("$inc",
        new BasicDBObject().append("total clients", 99));

    collection.update(new BasicDBObject().append("hosting", "hostB"), newDocument);

出力

{ "_id" : { "$oid" : "id"} , "hosting" : "hostA" , "type" : "vps" , "clients" : 1000}
{ "_id" : { "$oid" : "id"} , "hosting" : "hostB" , "type" : "dedicated server" , "clients" : 199}
{ "_id" : { "$oid" : "id"} , "hosting" : "hostC" , "type" : "vps" , "clients" : 900}

3. DBCollection.update() with multi

この例は、multiパラメータを使用して一致したドキュメントのセットを更新する方法を示しています。 タイプが「vps」のドキュメントを検索し、一致するすべてのドキュメントの「クライアント」の値を888に更新します。

    BasicDBObject updateQuery = new BasicDBObject();
    updateQuery.append("$set",
        new BasicDBObject().append("clients", "888"));

    BasicDBObject searchQuery = new BasicDBObject();
    searchQuery.append("type", "vps");

    collection.updateMulti(searchQuery, updateQuery);

    //below statement set multi to true.
    //collection.update(searchQuery, updateQuery, false, true);

出力

{ "_id" : { "$oid" : "id"} , "hosting" : "hostA" , "clients" : "888" , "type" : "vps"}
{ "_id" : { "$oid" : "id"} , "hosting" : "hostB" , "type" : "dedicated server" , "clients" : 100}
{ "_id" : { "$oid" : "id"} , "hosting" : "hostC" , "clients" : "888" , "type" : "vps"}

Note
multiをtrueに設定せずに更新した場合。

    BasicDBObject updateQuery = new BasicDBObject();
    updateQuery.append("$set",
        new BasicDBObject().append("clients", "888"));

    BasicDBObject searchQuery = new BasicDBObject();
    searchQuery.append("type", "vps");

    collection.update(searchQuery, updateQuery);

最初に一致したドキュメントのみが更新されることに気付くでしょう。

{"_id":{ "$oid" : "x"} , "hosting" : "hostA" , "clients" : "888" , "type" : "vps"}
{"_id":{ "$oid" : "x"} , "hosting" : "hostB" , "type" : "dedicated server" , "clients" : 100}
{"_id":{ "$oid" : "x"} , "hosting" : "hostC" , "type" : "vps" , "clients" : 900}

一致したドキュメントのセットを更新するには、「multi」をtrueに設定する必要があります。

4. 完全な例

上記のコードスニペットを組み合わせた完全な例。

package com.example.core;

import java.net.UnknownHostException;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.Mongo;
import com.mongodb.MongoException;

/**
 * Java MongoDB update document
 *
 * @author example
 *
 */

public class UpdateApp {

    public static void printAllDocuments(DBCollection collection) {
        DBCursor cursor = collection.find();
        while (cursor.hasNext()) {
            System.out.println(cursor.next());
        }
    }

    public static void removeAllDocuments(DBCollection collection) {
        collection.remove(new BasicDBObject());
    }

    public static void insertDummyDocuments(DBCollection collection) {
        BasicDBObject document = new BasicDBObject();
        document.put("hosting", "hostA");
        document.put("type", "vps");
        document.put("clients", 1000);

        BasicDBObject document2 = new BasicDBObject();
        document2.put("hosting", "hostB");
        document2.put("type", "dedicated server");
        document2.put("clients", 100);

        BasicDBObject document3 = new BasicDBObject();
        document3.put("hosting", "hostC");
        document3.put("type", "vps");
        document3.put("clients", 900);

        collection.insert(document);
        collection.insert(document2);
        collection.insert(document3);
    }

    public static void main(String[] args) {

    try {

      Mongo mongo = new Mongo("localhost", 27017);
      DB db = mongo.getDB("yourdb");

      // get a single collection
      DBCollection collection = db.getCollection("dummyColl");

      System.out.println("Testing 1...no $set");

      insertDummyDocuments(collection);

      // find hosting = hostB, and update the clients to 110
      BasicDBObject newDocument = new BasicDBObject();
      newDocument.put("clients", 110);

      BasicDBObject searchQuery = new BasicDBObject().append("hosting", "hostB");

      collection.update(searchQuery, newDocument);

      printAllDocuments(collection);
      removeAllDocuments(collection);

      System.out.println("\nTesting 1...with $set");

      insertDummyDocuments(collection);

      BasicDBObject updateDocument = new BasicDBObject();
      updateDocument.append("$set", new BasicDBObject().append("clients", 110));

      BasicDBObject searchQuery2 = new BasicDBObject().append("hosting", "hostB");

      collection.update(searchQuery2, updateDocument);

      printAllDocuments(collection);
      removeAllDocuments(collection);

      System.out.println("\nTesting 2... with $inc");
      insertDummyDocuments(collection);
      // find hosting = hostB and increase it's "clients" value by 99
      BasicDBObject newDocument2 = new BasicDBObject().append("$inc",
        new BasicDBObject().append("clients", 99));

      collection.update(new BasicDBObject().append("hosting", "hostB"), newDocument2);

      printAllDocuments(collection);
      removeAllDocuments(collection);

      System.out.println("\nTesting 3... with $multi");

      insertDummyDocuments(collection);
      // find type = vps , update all matched documents , clients value to 888
      BasicDBObject updateQuery = new BasicDBObject();
      updateQuery.append("$set", new BasicDBObject().append("clients", "888"));

      BasicDBObject searchQuery3 = new BasicDBObject();
      searchQuery3.append("type", "vps");

      collection.updateMulti(searchQuery3, updateQuery);
      // collection.update(searchQuery3, updateQuery, false, true);

      printAllDocuments(collection);
      removeAllDocuments(collection);

      System.out.println("Done");

    } catch (UnknownHostException e) {
        e.printStackTrace();
    } catch (MongoException e) {
        e.printStackTrace();
    }

    }
}

出力

Testing 1...no $set
{ "_id" : { "$oid" : "id"} , "hosting" : "hostA" , "type" : "vps" , "clients" : 1000}
{ "_id" : { "$oid" : "id"} , "clients" : 110}
{ "_id" : { "$oid" : "id"} , "hosting" : "hostC" , "type" : "vps" , "clients" : 900}

Testing 1...with $set
{ "_id" : { "$oid" : "id"} , "hosting" : "hostA" , "type" : "vps" , "clients" : 1000}
{ "_id" : { "$oid" : "id"} , "hosting" : "hostB" , "type" : "dedicated server" , "clients" : 110}
{ "_id" : { "$oid" : "id"} , "hosting" : "hostC" , "type" : "vps" , "clients" : 900}

Testing 2... with $inc
{ "_id" : { "$oid" : "id"} , "hosting" : "hostA" , "type" : "vps" , "clients" : 1000}
{ "_id" : { "$oid" : "id"} , "hosting" : "hostB" , "type" : "dedicated server" , "clients" : 199}
{ "_id" : { "$oid" : "id"} , "hosting" : "hostC" , "type" : "vps" , "clients" : 900}

Testing 3... with $multi
{ "_id" : { "$oid" : "id"} , "hosting" : "hostB" , "type" : "dedicated server" , "clients" : 100}
{ "_id" : { "$oid" : "id"} , "hosting" : "hostC" , "type" : "vps" , "clients" : 900}
{ "_id" : { "$oid" : "id"} , "clients" : "888" , "hosting" : "hostA" , "type" : "vps"}
Done