Skip to content

Commit 4e36763

Browse files
committed
* Support for Dot notation in documents
* extend Document functions with getValue. updateValue, getIntValue ... (with dot support)
1 parent 9c865a7 commit 4e36763

File tree

4 files changed

+163
-0
lines changed

4 files changed

+163
-0
lines changed

CHANGES.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## Versions
44

5+
### 1.9.5
6+
* Support for Dot notation in documents
7+
* extend Document functions with getValue. updateValue, getIntValue ... (with dot support)
8+
59
### 1.9.4
610
* Rewrite Docs and Samples
711
* Specs Setup Redesign

src/main/scala/com/sfxcode/nosql/mongo/bson/BsonConverter.scala

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,84 @@ import java.util.Date
77
import org.mongodb.scala.Document
88
import org.mongodb.scala.bson.BsonArray.fromIterable
99
import org.mongodb.scala.bson._
10+
import org.mongodb.scala.bson.{ObjectId, _}
1011

1112
import scala.collection.JavaConverters._
1213
import scala.collection.mutable
1314
import scala.util.matching.Regex
1415

1516
object BsonConverter {
17+
val DocumentKeyDivider = "."
18+
19+
def hasRelation(key: String): Boolean = key.indexOf(DocumentKeyDivider) != -1
20+
21+
def relationKey(key: String): String = key.substring(0, key.indexOf(DocumentKeyDivider))
22+
23+
def newKeyFromRelation(key: String): String = key.substring(key.indexOf(DocumentKeyDivider) + 1)
24+
25+
def lastKeyFromRelation(key: String): String = key.substring(key.lastIndexOf(DocumentKeyDivider) + 1)
26+
27+
def documentValueOption(document: Document, key: String): Option[Any] =
28+
if (hasRelation(key)) {
29+
val newKey = newKeyFromRelation(key)
30+
val relation = relationKey(key)
31+
32+
if (document.contains(relation) && documentValueOption(document, relation)
33+
.isInstanceOf[Option[Document]]) {
34+
val relatedDocument = documentValueOption(document, relation).asInstanceOf[Option[Document]].get
35+
documentValueOption(relatedDocument, newKey)
36+
}
37+
else {
38+
None
39+
}
40+
}
41+
else {
42+
if (document.contains(key)) {
43+
Some(fromBson(document(key)))
44+
}
45+
else {
46+
None
47+
}
48+
}
49+
50+
def updateDocumentValue(document: Document, key: String, value: Any): Document = {
51+
val doc = org.mongodb.scala.bson.collection.mutable.Document(document)
52+
val result = updateDocumentValueInternal(doc, key, value)
53+
Document(result)
54+
}
55+
56+
private def updateDocumentValueInternal(
57+
document: org.mongodb.scala.bson.collection.mutable.Document,
58+
key: String,
59+
value: Any,
60+
root: Option[org.mongodb.scala.bson.collection.mutable.Document] = None
61+
): org.mongodb.scala.bson.collection.mutable.Document =
62+
if (hasRelation(key)) {
63+
val newKey = newKeyFromRelation(key)
64+
val relation = relationKey(key)
65+
66+
var relatedDocument = Document()
67+
val relationValue = documentValueOption(Document(document), relation)
68+
if (relationValue.isDefined && relationValue.isInstanceOf[Option[Document]]) {
69+
relatedDocument = relationValue.asInstanceOf[Option[Document]].get
70+
}
71+
val mutableDoc = org.mongodb.scala.bson.collection.mutable.Document(relatedDocument)
72+
document.put(relation, mutableDoc)
73+
if (root.isEmpty)
74+
updateDocumentValueInternal(mutableDoc, newKey, value, Some(document))
75+
else
76+
updateDocumentValueInternal(mutableDoc, newKey, value, root)
77+
78+
}
79+
else {
80+
document.put(key, toBson(value))
81+
if (root.isEmpty) {
82+
document
83+
}
84+
else {
85+
root.get
86+
}
87+
}
1688

1789
var converterPlugin: AbstractConverterPlugin = new BaseConverterPlugin()
1890

src/main/scala/com/sfxcode/nosql/mongo/package.scala

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.sfxcode.nosql
22

3+
import java.util.Date
4+
35
import com.sfxcode.nosql.mongo.Converter
46
import com.sfxcode.nosql.mongo.bson.BsonConverter
57
import com.sfxcode.nosql.mongo.bson.convert.JsonDateTimeConverter
@@ -29,6 +31,46 @@ package object mongo extends MongoIncludes with DocumentIncludes {
2931
.outputMode(JsonMode.RELAXED)
3032
document.toJson(builder.build())
3133
}
34+
35+
def getValueOption(key: String): Option[Any] = BsonConverter.documentValueOption(document, key)
36+
37+
def getValue(key: String): Any = getValueOption(key).orNull
38+
39+
def getStringValue(key: String): String =
40+
getValue(key) match {
41+
case n: Any => n.toString
42+
case _ => ""
43+
}
44+
45+
def getLongValue(key: String): Long = {
46+
val value = getValue(key)
47+
value match {
48+
case n: Number => n.longValue()
49+
case s: String => s.toLongOption.getOrElse(0)
50+
case _ => 0
51+
}
52+
}
53+
54+
def getIntValue(key: String): Int = getLongValue(key).intValue()
55+
56+
def getDoubleValue(key: String): Double =
57+
getValue(key) match {
58+
case n: Number => n.doubleValue()
59+
case s: String => s.toDoubleOption.getOrElse(0)
60+
case _ => 0
61+
}
62+
63+
def getDateValue(key: String): Date = {
64+
val value = getValue(key)
65+
value match {
66+
case date: Date => date
67+
case _ => null
68+
}
69+
}
70+
71+
def getFloatValue(key: String): Float = getDoubleValue(key).floatValue()
72+
73+
def updateValue(key: String, value: Any): Any = BsonConverter.updateDocumentValue(document, key, value)
3274
}
3375
}
3476

src/test/scala/com/sfxcode/nosql/mongo/bson/BsonConverterSpec.scala

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package com.sfxcode.nosql.mongo.bson
22

3+
import org.mongodb.scala.bson.collection.mutable
34
import org.mongodb.scala.bson.{ObjectId, _}
45
import org.specs2.mutable.Specification
56

67
import scala.collection.mutable.ArrayBuffer
8+
import com.sfxcode.nosql.mongo._
79

810
/**
911
* Created by tom on 22.01.17.
@@ -59,6 +61,49 @@ class BsonConverterSpec extends Specification {
5961

6062
}
6163

64+
"evaluate dot notation" in {
65+
val document: mutable.Document = mutable.Document(Document())
66+
val secondLevelDocument = mutable.Document()
67+
secondLevelDocument.put("test", 42)
68+
document.put("secondLevelDocument", secondLevelDocument)
69+
70+
document.get("secondLevelDocument") must beSome
71+
72+
document.get("secondLevelDocument.test") must beNone
73+
74+
val v = BsonConverter.documentValueOption(Document(document), "secondLevelDocument.test")
75+
76+
true must beTrue
77+
}
78+
79+
"evaluate get with dot notation" in {
80+
val document: mutable.Document = mutable.Document(Document())
81+
val secondLevelDocument = mutable.Document()
82+
secondLevelDocument.put("test", 42)
83+
document.put("secondLevelDocument", secondLevelDocument)
84+
85+
document.get("secondLevelDocument") must beSome
86+
87+
document.get("secondLevelDocument.test") must beNone
88+
89+
val v = BsonConverter.documentValueOption(Document(document), "secondLevelDocument.test")
90+
91+
true must beTrue
92+
}
93+
94+
"evaluate put with dot notation" in {
95+
val document = Document()
96+
97+
var updated: Document = BsonConverter.updateDocumentValue(document, "test", 42)
98+
99+
updated.getIntValue("test") mustEqual (42)
100+
101+
updated = BsonConverter.updateDocumentValue(document, "test.test.test.test", 42)
102+
103+
updated.getIntValue("test.test.test.test") mustEqual 42
104+
true must beTrue
105+
}
106+
62107
}
63108

64109
}

0 commit comments

Comments
 (0)