使用Java连接MongoDB并进行访问(连接、搜索、插入、更新、删除)
以下是关于如何使用Java MongoDB驱动程序从Java访问MongoDB的方法的备忘录,专为完全初学者而写。
MongoDB具有许多功能,但本文只解释了使用Java MongoDB驱动程序进行简单CRUD操作的方法。
MongoDB的内容
RDB与之不同的术语。
如果不知道任何东西就阅读Java MongoDB Driver的文档,可能会感到困惑,所以至少应掌握RDB与其术语的区别。
RDB和MongoDB数据库结构的比较如下。
另外,可以在以下网站上了解MongoDB的特点等信息。
-
- Introduction to MongoDB — MongoDB Manual 2.6.3
-
- 触ってみよう!ビッグデータを支えるクラウド技術 – MongoDBを試してみよう:ITpro
- MongoDBでゆるふわDB体験:連載|gihyo.jp … 技術評論社
build.gradle文件的配置
在build.gradle中添加以下配置
dependencies {
...
compile group: 'org.mongodb', name:'mongo-java-driver', version:'2.12.3'
...
}
本次使用了Gradle,但如果想要自行解决依赖关系,可以从MongoDB Drivers下载合适的驱动程序并将其加入到路径中。
使用Java连接到MongoDB。
与服务器的连接和断开
// MongoDBサーバに接続
MongoClient client = new MongoClient("localhost", 27017);
// 利用するDBを取得
DB db = mongoClient.getDB( "mydb" );
...
// サーバから切断
client.close();
-
- new MongoClient()でコネクションプールのコネクションを1つをとってくる(らしい)
-
- スレッドセーフで、複数のスレッドで共有できるよう設計されているので、1つのアプリで1つのインスタンスでOK(らしい)
- getDB()したタイミングでデータベースがなければ勝手に生成される
请参考《Java驱动入门》以获取更详细信息。
确认身份
如果以安全模式(注:MongoDB手册2.6.3中的安全教程)启动,则需要进行身份验证。
MongoClient mongoClient = new MongoClient();
DB db = mongoClient.getDB("mydb");
boolean auth = db.authenticate(myUserName, myPassword);
获取收藏列表
获取数据库中集合的列表
Set<String> colls = db.getCollectionNames();
for (String s : colls) {
System.out.println(s);
}
获取指定的集合
您可以对获得的集合执行CRUD等操作。
DBCollection coll = db.getCollection("testCollection");
插入文件
在已获取的集合中插入文档。
若要插入以下结构的文档,
{
"name" : "MongoDB",
"type" : "database",
"count" : 1,
"info" : {
"x" : 203,
"y" : 102
}
}
以下是Java的源代码。
BasicDBObject doc = new BasicDBObject("name", "MongoDB")
.append("type", "database")
.append("count", 1)
.append("info", new BasicDBObject("x", 203).append("y", 102));
coll.insert(doc);
使用BasicDBObject类创建数据结构。
然后只需调用要插入的集合的insert()方法即可。
但是,说实话创建DBObject非常麻烦。。
要从JSON字符串创建DBObject,需按照以下方式进行描述。
DBObject json = (DBObject) JSON.parse("{'name':'mkyong', 'age':30}");
coll.insert(json);
搜索文档
搜索第一份文件。
要从集合中获取一份文件,只需按照以下方式进行描述。
DBObject myDoc = coll.findOne();
System.out.println(myDoc);
使用光标获取所有文件。
コレクションから全てのドキュメントを取得するにはfind()メソッドを利用します。
find()メソッドでは、クエリに一致した全てのドキュメントにアクセスできます。
DBCursor cursor = coll.find();
try {
while(cursor.hasNext()) {
System.out.println(cursor.next());
}
} finally {
cursor.close();
}
获取文档数量
要查询收藏中有多少个文档,可以使用getCount()方法。
long count = coll.getCount();
System.out.println(count + "件");
使用查询获取一个文档。
BasicDBObject query = new BasicDBObject("i", 71);
cursor = coll.find(query);
try {
while(cursor.hasNext()) {
System.out.println(cursor.next());
}
} finally {
cursor.close();
}
使用操作符进行查询以搜索文档。
MongoDBではクエリに$オペレータを利用して検索や集計等が行えます。
例えば、”qty”フィールドが20でないドキュメントを検索するには以下のように記述します
db.inventory.find( { qty: { $ne: 20 } } )
有关运算符的详细信息请参考《MongoDB 手册 2.6.3 — 运算符》。
操作符将其设置为DBObject,并将其视为常规字符串键。
query = new BasicDBObject("name",
new BasicDBObject("$ne", "mkyong")).append("count",
new BasicDBObject("$gt", 1));
cursor = coll.find(query);
try {
while (cursor.hasNext()) {
System.out.println("use $ operrator -> " + cursor.next());
}
} finally {
cursor.close();
}
不过,由于创建DBObject还是比较麻烦,所以我们将从JSON生成查询。
json = (DBObject) JSON
.parse("{'name':{$ne:'mkyong'}, 'count':{$gt:1}}");
cursor = coll.find(json);
try {
while (cursor.hasNext()) {
System.out.println("use $ ope(JSON) -> " + cursor.next());
}
} finally {
cursor.close();
}
coll.remove(new BasicDBObject());
文档更新
要更新文档,需要获取要更新的DBObject并进行修改,然后使用save()方法进行更新。
在此过程中,不要更改_id。因为会覆盖与DBObject的_id匹配的文档。
doc = coll.findOne();
doc.put("name", "MongoDB2"); // name属性を更新
doc.put("age", "15"); // age属性を追加
coll.save(doc);
删除文件
要删除文档,需要获取要删除的DBObject,并使用remove()方法进行删除。
doc = coll.findOne();
coll.remove(doc);
删除收藏
如果要删除集合,请使用drop()方法。
System.out.println(db.getCollectionNames());
coll.drop();
System.out.println(db.getCollectionNames());
样本代码
以下为处理摘要(无需认证):
MongoClient client = null;
try {
// MondoDBサーバへの接続
client = new MongoClient("localhost", 27017);
// client = new MongoClient();
// 使用するDBの指定
DB db = client.getDB("mydb");
DBCollection coll = db.getCollection("testCollection");
// Insert(append版)
DBObject doc = new BasicDBObject("name", "MongoDB")
.append("type", "database")
.append("count", 1)
.append("info",
new BasicDBObject("x", 203).append("y", 102));
coll.insert(doc);
doc = new BasicDBObject("name", "MongoDB")
.append("type", "database")
.append("count", 2)
.append("info",
new BasicDBObject("x", 400).append("y", -10));
coll.insert(doc);
// Insert(JSON版)
DBObject json = (DBObject) JSON
.parse("{'name':'mkyong', 'age':30}");
coll.insert(json);
// 1件だけ検索
DBObject myDoc = coll.findOne();
System.out.println("findOne() -> " + myDoc);
// カーソルを使って全件取得
DBCursor cursor = coll.find();
try {
while (cursor.hasNext()) {
System.out.println("DBCursor - > " + cursor.next());
}
} finally {
cursor.close();
}
// ドキュメント件数取得
long count = coll.getCount();
System.out.println(count + "件");
// クエリを使って1件のドキュメントを取得する
BasicDBObject query = new BasicDBObject("name", "MongoDB");
cursor = coll.find(query);
try {
while (cursor.hasNext()) {
System.out.println("use query -> " + cursor.next());
}
} finally {
cursor.close();
}
// $オペレータを使ったクエリ
query = new BasicDBObject("name",
new BasicDBObject("$ne", "mkyong")).append("count",
new BasicDBObject("$gt", 1));
cursor = coll.find(query);
try {
while (cursor.hasNext()) {
System.out.println("use $ operator -> " + cursor.next());
}
} finally {
cursor.close();
}
// JSONからクエリを生成
json = (DBObject) JSON
.parse("{'name':{$ne:'mkyong'}, 'count':{$gt:1}}");
cursor = coll.find(json);
try {
while (cursor.hasNext()) {
System.out.println("use $ ope(JSON) -> " + cursor.next());
}
} finally {
cursor.close();
}
// ドキュメントをアップデート
doc = coll.findOne();
doc.put("name", "MongoDB2"); // name属性を更新
doc.put("age", "15"); // age属性を追加
coll.save(doc);
cursor = coll.find();
try {
while (cursor.hasNext()) {
System.out.println("updated -> " + cursor.next());
}
} finally {
cursor.close();
}
// ドキュメントを削除
doc = coll.findOne();
coll.remove(doc);
cursor = coll.find();
try {
while (cursor.hasNext()) {
System.out.println("deleted -> " + cursor.next());
}
} finally {
cursor.close();
}
// コレクション削除
System.out.println("コレクション削除前: " + db.getCollectionNames());
coll.drop();
System.out.println("コレクション削除後: " + db.getCollectionNames());
coll.remove(new BasicDBObject());
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (client != null) {
client.close();
}
}
除此之外,还有其他引起了我的兴趣的事情。
除了上述的内容,我还了解了一些其他内容并做了备忘录。
交易
MongoDB没有事务,并且是后取胜的,所以似乎要使用乐观锁进行排他控制。
(1)通过查询提取文档。
(2)保存旧值。
(3)更新文档。
(4)将旧值(包括 _id)作为第一个参数,将更新后的新文档作为第二个参数,调用 update 方法。如果文档已被改写,则更新将失败。
(5)如果更新失败,则重新执行(1)。
听说是这样的。
此外,即使在一系列的操作中发生错误,也无法通过回滚来撤销之前的处理。似乎可以通过使用db.getLastError()方法来确认最近发生的错误。
save()、insert()和update()的区别.
由于save()方法、insert()方法和update()方法的使用差异不太明确,所以总结如下。
详细情况请参考javadoc。(DBCollection)
1. 如果使用updateMulti()方法,或将update()方法的第4个参数设置为true时,可以批量更新多个记录。否则,只更新第一条记录。
2. 如果将update()方法的第3个参数设置为true,则会执行Upsert操作。
批量操作 (pī zuò)
-
- 大量のデータを操作する場合はBulkオペレーションを利用すると速いらしい
-
- insert/update/removeが一括で処理できる
-
- Buklオペレーションには2種類ある
Ordered bulk operation:順序を保証
Unordered bulk operations:順序を保証しない(並行処理)
这个语句的addBatch()和executeBatch()函数看起来很相似。
样例代码如下所示。
// 1. Ordered bulk operation
BulkWriteOperation builder = coll.initializeOrderedBulkOperation();
builder.insert(new BasicDBObject("_id", 1));
builder.insert(new BasicDBObject("_id", 2));
builder.insert(new BasicDBObject("_id", 3));
builder.find(new BasicDBObject("_id", 1)).updateOne(new BasicDBObject("$set", new BasicDBObject("x", 2)));
builder.find(new BasicDBObject("_id", 2)).removeOne();
builder.find(new BasicDBObject("_id", 3)).replaceOne(new BasicDBObject("_id", 3).append("x", 4));
BulkWriteResult result = builder.execute();
// 2. Unordered bulk operation - no guarantee of order of operation
builder = coll.initializeUnorderedBulkOperation();
builder.find(new BasicDBObject("_id", 1)).removeOne();
builder.find(new BasicDBObject("_id", 2)).removeOne();
result = builder.execute();