web-dev-qa-db-ja.com

javaを使用して、JsonファイルからMongodbにデータをインポートするにはどうすればよいですか?

MongodbファイルからJsonにデータをインポートするのに苦労しています。
コマンドラインでもmongoimport commandを使用して同じことができます。
たくさん調べて試しましたが、Javaを使用してJsonファイルからインポートできませんでした。

sample.json

    { "test_id" : 1245362, "name" : "ganesh", "age" : "28", "Job" : 
       {"company name" : "company1", "designation" : "SSE" } 
    }

    { "test_id" : 254152, "name" : "Alex", "age" : "26", "Job" :
       {"company name" : "company2", "designation" : "ML" } 
    }

お時間をいただきありがとうございます。 〜ガネーシャ〜

9

JSON文字列をそれぞれ読み取ることができるとします。たとえば、最初のJSONテキストを読みます

{ "test_id" : 1245362, "name" : "ganesh", "age" : "28", "Job" : 
   {"company name" : "company1", "designation" : "SSE" } 
}

それを変数(String json1)に割り当てます。次のステップは、それを解析することです。

DBObject dbo = (DBObject) com.mongodb.util.JSON.parse(json1);

すべてdboをリストに入れ、

List<DBObject> list = new ArrayList<>();
list.add(dbo);

次に、それらをデータベースに保存します。

new MongoClient().getDB("test").getCollection("collection").insert(list);

編集:

最新のMongoDBバージョンでは、DBObjectの代わりにDocumentsを使用する必要があり、オブジェクトを追加する方法が異なって見えるようになりました。更新された例を次に示します。

インポートは次のとおりです。

import com.mongodb.MongoClient;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;

コードはこれを望みます(編集の上のテキストを参照):

Document doc = Document.parse(json1);
new MongoClient().getDataBase("db").getCollection("collection").insertOne(doc);

リストを使ってそれを行うこともできます。しかし、あなたは必要です

new MongoClient().getDataBase("db").getCollection("collection").insertMany(list);

しかし、私はこの解決策に問題があると思います。入力するとき:

db.collection.find()

コレクション内のすべてのオブジェクトを取得するためのmongoシェルでは、結果は次のようになります。

{ "_id" : ObjectId("56a0d2ddbc7c512984be5d97"),
    "test_id" : 1245362, "name" : "ganesh", "age" : "28", "Job" :
        { "company name" : "company1", "designation" : "SSE" 
    }
}

これは以前とまったく同じではありません。

12
Wizard

ランタイムr = Runtime.getRuntime();

プロセスp = null;

--dirは、mongoimportがある場所へのパスです。

File dir = new File( "C:\ Program Files\MongoDB\Server\3.2\bin");

-この行は、dirを指定してシェルを開きます。インポートのコマンドは、コマンドプロモートでmongoimportを使用するのとまったく同じです。

p = r.exec( "c:\ windows\system32\cmd.exe/c mongoimport --db mydb --collection student --type csv --file student.csv --headerline"、null、dir );

2
Robin

私自身も同様の「問題」を抱えていて、 JacksonPOJO databinding 、およびMorphiaを使用することになりました。

これはスレッジハンマーでナットを割るような音ですが、実際には非常に使いやすく、堅牢で非常にパフォーマンスが高く、コードを賢く維持するのも簡単です。

小さな注意点:再利用する場合は、test_idフィールドをMongoDBの_idにマップする必要があります。

ステップ1:注釈付きBeanを作成する

JSONファイルからPOJOにデータをマップする方法をJacksonにヒントする必要があります。読みやすくするために、クラスを少し短くしました。

@JsonRootName(value="person")
@Entity
public class Person {

  @JsonProperty(value="test_id")
  @Id
  Integer id;

  String name;

  public Integer getId() {
    return id;
  }

  public void setId(Integer id) {
    this.id = id;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

}

埋め込みドキュメントJobについては、リンクされているPOJOデータバインディングの例をご覧ください。

ステップ2:POJOをマップし、データストアを作成します

アプリケーションの初期化中のどこかで、注釈付きのPOJOをマップする必要があります。すでにMongoClientを持っているはずなので、それを再利用します;)

Morphia morphia = new Morphia();
morphia.map(Person.class);

/* You can reuse this datastore */
Datastore datastore = morphia.createDatastore(mongoClient, "myDatabase");

/* 
 * Jackson's ObjectMapper, which is reusable, too,
 * does all the magic.
 */
ObjectMapper mapper = new ObjectMapper();

実際のインポートを行います

これで、特定のJSONファイルのインポートが同じくらい簡単になります

public Boolean importJson(Datastore ds, ObjectMapper mapper, String filename) {

    try {           
        JsonParser parser = new JsonFactory().createParser(new FileReader(filename));
        Iterator<Person> it = mapper.readValues(parser, Person.class);

        while(it.hasNext()) {
            ds.save(it.next());
        }

        return Boolean.TRUE;

    } catch (JsonParseException e) {
        /* Json was invalid, deal with it here */
    } catch (JsonMappingException e) {
        /* Jackson was not able to map
         * the JSON values to the bean properties,
         * possibly because of
         * insufficient mapping information.
         */
    } catch (IOException e) {
        /* Most likely, the file was not readable
         * Should be rather thrown, but was
         * cought for the sake of showing what can happen
         */
    }

    return Boolean.FALSE;
}

少し再ファットコアを作成することで、これをJacksonアノテーション付きBeanの汎用インポーターに変換できます。明らかに、私はいくつかの特別なケースを省略しましたが、これはこの回答の範囲外になります。

1
List<Document> jsonList = new ArrayList<Document>();
net.sf.json.JSONArray array = net.sf.json.JSONArray.fromObject(json);
for (Object object : array) {
    net.sf.json.JSONObject jsonStr = (net.sf.json.JSONObject)JSONSerializer.toJSON(object);
    Document jsnObject = Document.parse(jsonStr.toString()); 
    jsonList.add(jsnObject);
}
collection.insertMany(jsonList);
1
user3041121

3.2ドライバーでは、mongoコレクションとjsonドキュメントのコレクションがある場合(例:

MongoCollection<Document> collection = ...
List<String> jsons = ...

個別に挿入できます。

jsons.stream().map(Document::parse).forEach(collection::insertOne);

またはバルク:

collection.insertMany(
        jsons.stream().map(Document::parse).collect(Collectors.toList())
); 
1
David Soroko

私は今日この問題に直面し、別の方法で解決しましたが、ここでは誰も私を満足させませんでしたので、私の余分な貢献を楽しんでください。パフォーマンスは、30kのドキュメントをエクスポートし、統合テストケース用にSpringbootアプリにインポートするのに十分です(数秒かかります)。

まず、最初にデータをエクスポートする方法が重要です。 Javaアプリで解析できる1つのドキュメントが各行に含まれているファイルが必要でした。

mongo db --eval 'db.data.find({}).limit(30000).forEach(function(f){print(tojson(f, "", true))})' --quiet > dataset.json

次に、resourcesフォルダーからファイルを取得して解析し、行を抽出して、mongoTemplateで処理します。バッファを使用できます。

@Autowired    
private MongoTemplate mongoTemplate;

public void createDataSet(){
    mongoTemplate.dropCollection("data");
    try {
        InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(DATASET_JSON);
        List<Document> documents = new ArrayList<>();
        String line;
        InputStreamReader isr = new InputStreamReader(inputStream, Charset.forName("UTF-8"));
        BufferedReader br = new BufferedReader(isr);
        while ((line = br.readLine()) != null) {
            documents.add(Document.parse(line));
        }
        mongoTemplate.insert(documents,"data");


    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}
1
Jeremie