[Groovy] 一种很酷的语言Groovy,可以简单地处理MongoDB -Groovy的应用篇-
这是G* Advent Calendar 2015第八天的文章。
首先
在昨天的文章中,我展示了如何使用Groovy来处理MongoDB的基本知识。
这次,让我们进一步使用Groovy的功能来更深入地了解它的魅力!
如果你时间有限的话,我也在最后附上了整个代码供您参考。
将文档生成变得更简单
昨天在文章中提到了生成文件的代码。
// 1件登録する
Document doc = new Document("name", "MongoDB")
.append("type", "database")
.append("count", 1)
.append("info", new Document("x", 203).append("y", 102))
collection.insertOne(doc)
生成的文档(JSON)如下所示。
{
"name" : "MongoDB",
"type" : "database",
"count" : 1,
"info" : {
"x" : 203,
"y" : 102
}
}
哎呀!简单简单!
但是仔细一看,每次都要在每个字段后面加上append,这样太冗长了。
而且如果是嵌套的情况,还得再生成一个Document对象…
好的!有办法解决这个问题!
虽然话题听起来有点复杂,但实际上,Document类在构造函数中可以接受一个Map作为参数。
此外!在Groovy中,生成Map非常便捷。
现在,让我们看一下与上述代码等价的Groovy Map版本!
def doc2 = [
"name": "MongoDB",
"type": "database",
"count": 1,
"info": ["x": 203, "y": 102]
]
collection.insertOne(new Document(doc2))
这就是它!就只有这个!这段代码和一开始的一个追加代码完全相同!当使用最新的MongoDB官方Java驱动和Groovy功能结合时,代码会变得如此简洁!
将JSON(文本)保存
使用Groovy的GString,您可以轻松地将JSON表示为文本。
您无需声明任何特殊内容来使用GString。而且,如果您用三个双引号括起来,就可以轻松地编写换行符和转义字符。
另外,Document类作为静态方法提供了用于解析文本格式的JSON的parse方法,所以您可以将JSON文本传递给它,然后将其轻松保存到MongoDB中。
String jsonAsText = """
{
"name": "Koji",
"age": 30,
"address":{
"city": "Tokyo",
"country": "Japan"
},
"married": true,
"favorites": ["Groovy", "Grails", "MongoDB"]
}
"""
collection.insertOne(Document.parse(jsonAsText))
通常的JSON被存储为文本(字符串)并赋值给jsonAsText变量,然后传递给Document.parse()方法。
通过这样做,就实现了使用Map生成Document实例的相同效果。
将JSON(对象)进行存储
现在,这到底是什么事情呢?
基本上,使用上述文本表示JSON的方法非常简单,因为可以在字符串中处理变量,所以没有什么问题。但是,在Groovy中还有一个名为JsonBuilder的类,可以简单地生成JSON对象。下次我们试着用JsonBuilder来做同样的事情。
// JsonBuilder経由
// Groovy上で、複雑なJSONを生成する場合、JsonBuilderがとっても便利。
def builder = new groovy.json.JsonBuilder()
builder {
name 'Koji'
age 30
address(
city: 'Tokyo',
country: 'Japan'
)
married true
favorites 'Groovy', 'Grails', 'MongoDB'
}
collection.insertOne(Document.parse(builder.toPrettyString()))
実行結果は上記の「JSON(テキスト)を保存する」と全く同じです。
JsonBuilderのインスタンスを生成して値をその中に記述していくだけです。
ちょっと書き方が独特で、通常JSONは “KEY: VALUE”の形式ですが、上記のJsonBuilderの書き方だとキーとバリューの間のコロンが必要なくなります。(が、addressの部分のようにそうでもない例外もあります。。。)
そしてDocument.parseにtoStringした値を渡すだけでOKです。
ちなみに、JsonBuilderにはbuilder.toPrettyStringというメソッドが用意されていて、buiderの値を綺麗に表示することが出来ます。
// println builder.toPrettyString()を実行した結果
{
"name": "Koji",
"age": 30,
"address": {
"city": "Tokyo",
"country": "Japan"
},
"married": true,
"favorites": [
"Groovy",
"Grails",
"MongoDB"
]
}
编辑并保存JSON(文本)
现在,我们来看看关于“保存JSON(文本)”的应用部分。
JSON已经保存在String类型的变量jsonAsText中。
在这个状态下,如何才能修改值呢?
因为是文本,所以可以使用正则表达式进行替换。但是,这样做比较麻烦,不是吗?
如果使用Groovy,可以很容易地实现!
在Groovy中,有一个名为JsonSlurper的类,它可以将文本的JSON转换为类似Map的对象,利用它就可以实现。
现在让我们来看一下代码。
// JsonSlurper経由
// JsonSlurperを使うと、テキストで受け取ったJSONでも、通常のJSONオブジェクトのようにその中身を編集することができる
def slurper = new groovy.json.JsonSlurper().parseText(jsonAsText)
slurper.name = "JsonSlurper of Groovy!"
slurper.hoge = "piyo" // 存在しないフィールの追加もなんのその!
slurper.married = false
collection.insertOne(new Document(slurper))
JsonSlurperのインスタンスを生成して、parseTextメソッドにすでに存在しているテキスト形式のJSONを渡すだけです。
あとは通常のGroovyのMapのように扱えます!
そしてこのJsonSlurperインスタンスをnew Documentに渡してあげればちゃんとMongoDBに保存されます。
额外内容1(特定文档的更新)
在MongoDB中,updateOne和updateMany用于检索和更新目标文档。
那么,如果要在Groovy中处理相关文档的信息,并进一步更新该文档,应该怎么做呢?
实际上,我还没有完全理解…
暂时,可以使用以下代码检索文档,并将每个type字段的内容附加到相应的_id字段的值,进行更新。可能还有其他更好的方法,但这个暂时应该没有问题。
collection.find(eq("name", "MongoDB")).collect {
["_id":it._id, "newType": "NoSQL(ObjectId = ${it._id})"]
}.each {
collection.updateOne(eq("_id", it._id), set("type", it.newType.toString()))
}
额外2(JsonBuilder的组合)
请问是什么意思呢?简单来说,就是在JsonBuilder实例内处理另一个JsonBuilder实例。
然而,有点特殊的是,另一个JsonBuilder在JsonBuilder内被使用时,必须通过.content来获取其值。
可能听起来有点难以理解。让我们来看看源代码吧!
def builder2 = new groovy.json.JsonBuilder()
builder2 {
abc 'def'
fromOtherJsonBuilder builder.content
}
println builder2.toPrettyString()
collection.insertOne(Document.parse(builder2.toPrettyString()))
用以下的代码将一个新的文档保存在MongoDB中:
“`
println builder2.toPrettyString()
“`
其中,builder2.toPrettyString()方法打印的JSON如下:
{
"abc": "def",
"fromOtherJsonBuilder": {
"name": "Koji",
"age": 30,
"address": {
"city": "Tokyo",
"country": "Japan"
},
"married": true,
"favorites": [
"Groovy",
"Grails",
"MongoDB"
]
}
}
没有什么特别困难的地方,这只是将原本存在的JsonBuilder对象用另一个JsonBuilder包装起来的形式而已。
通过查看fromOtherJsonBuilder builder.content,可以看出只需简单地从另一个JsonBuilder实例的.content中获取内容即可。
在像这样的例子中,将已经存在的JSON用另一个JSON包装起来,当然可以使用文本方式实现,但代码可能变得混乱不堪。
在这种情况下,JsonBuilder可以发挥作用。
概述
いかがだったでしょうか。
Groovyを使えば、MongoDB用の公式Java用ドライバを使って、さらに便利、シンプルにMongoDBを扱えることがわかったのではないでしょうか。
最後に、今回のコードの全体を記述して終わりにさせていただきます。
ありがとうございました。
明天是@h1romas4先生!
@Grab(group='org.mongodb', module='mongo-java-driver', version='3.1.1')
import com.mongodb.MongoClient
import com.mongodb.client.MongoDatabase
import com.mongodb.client.MongoCollection
import org.bson.Document
import static com.mongodb.client.model.Filters.*
import static com.mongodb.client.model.Sorts.*
import static com.mongodb.client.model.Updates.*
import com.mongodb.client.result.UpdateResult
// MongoDB本体に接続
MongoClient mongoClient = new MongoClient("localhost", 27017)
// 利用するデータベースに接続(データベース名はgroovy)
MongoDatabase db = mongoClient.getDatabase("groovy")
// 利用するコレクションに接続(コレクション名はtest)
MongoCollection<Document> collection = db.getCollection("test")
// DELETE ALL EXISTING DOCUMENTS
if (collection.count() > 0) {
collection.deleteMany(new Document())
}
// 1件登録する
Document doc = new Document("name", "MongoDB")
.append("type", "database")
.append("count", 1)
.append("info", new Document("x", 203).append("y", 102))
collection.insertOne(doc)
// 上の例と等価
def doc2 = [
"name": "MongoDB",
"type": "database",
"count": 1,
"info": ["x": 203, "y": 102]
]
collection.insertOne(new Document(doc2))
// テキストなJSONを保存する
String jsonAsText = """
{
"name": "Koji",
"age": 30,
"address":{
"city": "Tokyo",
"country": "Japan"
},
"married": true,
"favorites": ["Groovy", "Grails", "MongoDB"]
}
"""
collection.insertOne(Document.parse(jsonAsText))
// JsonBuilder経由
// Groovy上で、複雑なJSONを生成する場合、JsonBuilderがとっても便利。
// ちょっと書き方が独特で、通常JSONは "KEY: VALUE"の形式だけど、間のコロンが必要なくなる。
def builder = new groovy.json.JsonBuilder()
builder {
name 'Koji'
age 30
address(
city: 'Tokyo',
country: 'Japan',
)
married true
favorites 'Groovy', 'Grails', 'MongoDB'
}
collection.insertOne(Document.parse(builder.toString()))
// JsonSlurper経由
// JsonSlurperを使うと、テキストで受け取ったJSONでも、通常のJSONオブジェクトのようにその中編みを編集することができる
def slurper = new groovy.json.JsonSlurper().parseText(jsonAsText)
slurper.name = "JsonSlurper of Groovy!"
slurper.hoge = "piyo" // 存在しないフィールの追加もなんのその!
slurper.married = false
collection.insertOne(new Document(slurper))