Skip to content

Commit 912ccdb

Browse files
committed
refactor Index Handling
1 parent 52d77f2 commit 912ccdb

File tree

4 files changed

+194
-36
lines changed

4 files changed

+194
-36
lines changed
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package com.sfxcode.nosql.mongo.database
2+
3+
import com.sfxcode.nosql.mongo.operation.ObservableIncludes
4+
import org.mongodb.scala.ListIndexesObservable
5+
import org.mongodb.scala.model.IndexOptions
6+
7+
case class MongoIndex(name: String, key: String, ascending: Int, version: Int, namespace: String, keys:Map[String, Any] = Map())
8+
9+
object MongoIndex extends ObservableIncludes {
10+
11+
def indexOptionsWithName(name: Option[String]) =
12+
if (name.isDefined)
13+
IndexOptions().name(name.get)
14+
else
15+
IndexOptions()
16+
17+
def hasIndexForFieldWithName(listIndexesObservable: ListIndexesObservable[Map[String, Any]],
18+
fieldName: String,
19+
maxWait: Int = DefaultMaxWait): Boolean =
20+
convertIndexDocumentsToMongoIndexList(listIndexesObservable).exists(index => index.key == fieldName)
21+
22+
def convertIndexDocumentsToMongoIndexList(listIndexesObservable: ListIndexesObservable[Map[String, Any]],
23+
maxWait: Int = DefaultMaxWait): List[MongoIndex] = {
24+
var result = List[MongoIndex]()
25+
try {
26+
result = listIndexesObservable
27+
.resultList(maxWait)
28+
.map(
29+
indexOptions =>
30+
MongoIndex(
31+
indexOptions("name").toString, {
32+
if (indexOptions.contains("textIndexVersion")) {
33+
indexOptions("name").toString.substring(0, indexOptions("name").toString.indexOf("_"))
34+
} else {
35+
indexOptions("key").asInstanceOf[Map[String, _]].head.asInstanceOf[(String, Int)]._1
36+
}
37+
}, {
38+
if (indexOptions.contains("textIndexVersion")) {
39+
indexOptions("textIndexVersion").toString.toInt
40+
} else {
41+
val value = indexOptions("key").asInstanceOf[Map[String, _]].head._2.toString
42+
if (value.matches("[0-9]")) {
43+
value.toInt
44+
} else {
45+
0
46+
}
47+
}
48+
},
49+
indexOptions("v").toString.toInt,
50+
indexOptions("ns").toString,
51+
indexOptions("key").asInstanceOf[Map[String, _]]
52+
)
53+
)
54+
}
55+
result
56+
}
57+
58+
}
Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
package com.sfxcode.nosql.mongo.operation
22

3+
import com.sfxcode.nosql.mongo.database.MongoIndex
34
import com.typesafe.scalalogging.LazyLogging
45
import org.mongodb.scala.bson.conversions.Bson
5-
import org.mongodb.scala.model.Indexes.hashed
66
import org.mongodb.scala.model.Sorts._
7-
import org.mongodb.scala.model.{ CountOptions, DropIndexOptions, IndexOptions }
7+
import org.mongodb.scala.model.{ CountOptions, DropIndexOptions, IndexOptions, Indexes }
88
import org.mongodb.scala.{ Document, ListIndexesObservable, MongoCollection, Observable, SingleObservable }
99

10+
import scala.concurrent.duration.Duration
1011
import scala.reflect.ClassTag
1112

1213
abstract class Base[A]()(implicit ct: ClassTag[A]) extends LazyLogging {
@@ -18,32 +19,53 @@ abstract class Base[A]()(implicit ct: ClassTag[A]) extends LazyLogging {
1819

1920
def drop(): Observable[Void] = coll.drop()
2021

21-
def createIndexForField(field: String, sortAscending: Boolean = true, options: IndexOptions = IndexOptions()): SingleObservable[String] =
22+
def createIndexForField(fieldName: String,
23+
sortAscending: Boolean = true,
24+
options: IndexOptions = IndexOptions()): SingleObservable[String] =
2225
if (sortAscending) {
23-
createIndex(ascending(field), options)
26+
createIndex(ascending(fieldName), options)
2427
} else {
25-
createIndex(descending(field), options)
28+
createIndex(descending(fieldName), options)
2629
}
2730

28-
def createUniqueIndexForField(
29-
collectionName: String,
30-
fieldName: String,
31-
ascending: Boolean = true): Unit =
32-
createIndexForField(fieldName, ascending, IndexOptions().unique(true))
31+
def createIndexForFieldWithName(fieldName: String,
32+
sortAscending: Boolean = true,
33+
name: String): SingleObservable[String] = {
34+
createIndexForField(fieldName, sortAscending, MongoIndex.indexOptionsWithName(Some(name)))
35+
}
36+
37+
def createUniqueIndexForField(fieldName: String,
38+
sortAscending: Boolean = true,
39+
name: Option[String] = None): SingleObservable[String] =
40+
createIndexForField(fieldName, sortAscending, MongoIndex.indexOptionsWithName(name).unique(true))
41+
42+
def createHashedIndexForField(fieldName: String, options: IndexOptions = IndexOptions()): SingleObservable[String] =
43+
createIndex(Indexes.hashed(fieldName), IndexOptions())
44+
45+
def createTextIndexForField(fieldName: String, options: IndexOptions = IndexOptions()): SingleObservable[String] =
46+
createIndex(Indexes.text(fieldName), IndexOptions())
47+
48+
def createExpiringIndexForField(fieldName: String,
49+
duration: Duration,
50+
sortAscending: Boolean = true,
51+
name: Option[String] = None): SingleObservable[String] =
52+
createIndexForField(fieldName,
53+
sortAscending,
54+
MongoIndex.indexOptionsWithName(name).expireAfter(duration._1, duration._2))
3355

3456
def createIndex(key: Bson, options: IndexOptions = IndexOptions()): SingleObservable[String] =
3557
coll.createIndex(key, options)
3658

3759
def dropIndexForName(name: String, options: DropIndexOptions = new DropIndexOptions()): SingleObservable[Void] =
3860
coll.dropIndex(name, options)
3961

40-
def dropIndex(keys: Bson, options: DropIndexOptions = new DropIndexOptions()): SingleObservable[Void] = coll.dropIndex(keys, options)
41-
42-
def createHashedIndex(
43-
fieldName: String,
44-
options: IndexOptions = IndexOptions()): SingleObservable[String] =
45-
coll.createIndex(hashed(fieldName), options)
62+
def dropIndex(keys: Bson, options: DropIndexOptions = new DropIndexOptions()): SingleObservable[Void] =
63+
coll.dropIndex(keys, options)
4664

4765
def listIndexes: ListIndexesObservable[Map[String, Any]] = coll.listIndexes[Map[String, Any]]()
4866

67+
def indexList(): List[MongoIndex] = MongoIndex.convertIndexDocumentsToMongoIndexList(listIndexes)
68+
69+
def hasIndexForField(fieldName: String) = MongoIndex.hasIndexForFieldWithName(listIndexes, fieldName)
70+
4971
}

src/test/scala/com/sfxcode/nosql/mongo/operation/BaseSpec.scala

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package com.sfxcode.nosql.mongo.operation
22

3+
import com.sfxcode.nosql.mongo.TestDatabase._
34
import com.sfxcode.nosql.mongo._
4-
import com.sfxcode.nosql.mongo.model.{Author, Book}
5-
import TestDatabase._
5+
import com.sfxcode.nosql.mongo.model.{ Author, Book }
66
import org.mongodb.scala.result.InsertOneResult
77
import org.specs2.mutable.Specification
88
import org.specs2.specification.BeforeAll
@@ -42,24 +42,6 @@ class BaseSpec extends Specification with BeforeAll {
4242
genderList must have size 1
4343
}
4444

45-
"must create / drop indexes for key" in {
46-
47-
var createIndexResult: String = PersonDAO.createIndexForField("name")
48-
49-
createIndexResult must be equalTo "name_1"
50-
51-
PersonDAO.createIndexForField("name").headResult() must be equalTo "name_1"
52-
53-
val dropIndexResult: Void = PersonDAO.dropIndexForName("name_1")
54-
55-
createIndexResult = PersonDAO.createIndexForField("name")
56-
57-
createIndexResult must be equalTo "name_1"
58-
59-
60-
61-
}
62-
6345
}
6446

6547
override def beforeAll: Unit = BookDAO.drop().headResult()
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package com.sfxcode.nosql.mongo.operation
2+
3+
import com.sfxcode.nosql.mongo.TestDatabase._
4+
import com.sfxcode.nosql.mongo._
5+
import com.sfxcode.nosql.mongo.database.MongoIndex
6+
import org.specs2.mutable.Specification
7+
import org.specs2.specification.BeforeAll
8+
9+
class IndexSpec extends Specification with BeforeAll {
10+
11+
sequential
12+
13+
"Base Index Operations" should {
14+
15+
"return an index list" in {
16+
17+
val list = PersonDAO.indexList
18+
list must haveSize(1)
19+
20+
val mongoIndex: MongoIndex = list.head
21+
mongoIndex.name must be equalTo "_id_"
22+
mongoIndex.key must be equalTo "_id"
23+
mongoIndex.ascending must be equalTo 1
24+
mongoIndex.namespace must be equalTo "simple_mongo_test.person"
25+
mongoIndex.version must be equalTo 2
26+
mongoIndex.keys must haveSize(1)
27+
mongoIndex.keys.head._1 must be equalTo "_id"
28+
mongoIndex.keys.head._2 must be equalTo 1
29+
30+
}
31+
32+
"create / drop indexes for key" in {
33+
34+
var createIndexResult: String = PersonDAO.createIndexForField("name")
35+
36+
createIndexResult must be equalTo "name_1"
37+
38+
PersonDAO.indexList must haveSize(2)
39+
40+
val dropIndexResult: Void = PersonDAO.dropIndexForName(createIndexResult)
41+
42+
PersonDAO.indexList must haveSize(1)
43+
}
44+
45+
"evaluate has index" in {
46+
47+
PersonDAO.hasIndexForField("_id") must beTrue
48+
49+
PersonDAO.hasIndexForField("unknown") must beFalse
50+
}
51+
52+
"create descending index for key" in {
53+
54+
var createIndexResult: String = PersonDAO.createIndexForFieldWithName("name", sortAscending = false, "myIndex")
55+
56+
createIndexResult must be equalTo "myIndex"
57+
58+
PersonDAO.indexList must haveSize(2)
59+
60+
PersonDAO.dropIndexForName(createIndexResult).headResult()
61+
62+
PersonDAO.indexList must haveSize(1)
63+
}
64+
65+
"create unique index for key" in {
66+
67+
var createIndexResult: String = PersonDAO.createUniqueIndexForField("id", sortAscending = false, Some("myUniqueIndex"))
68+
69+
createIndexResult must be equalTo "myUniqueIndex"
70+
71+
PersonDAO.indexList must haveSize(2)
72+
73+
PersonDAO.dropIndexForName(createIndexResult).headResult()
74+
75+
PersonDAO.indexList must haveSize(1)
76+
}
77+
78+
"create hashed index for key" in {
79+
80+
var createIndexResult: String = PersonDAO.createHashedIndexForField("email")
81+
82+
createIndexResult must be equalTo "email_hashed"
83+
84+
PersonDAO.indexList must haveSize(2)
85+
86+
PersonDAO.dropIndexForName(createIndexResult).headResult()
87+
88+
PersonDAO.indexList must haveSize(1)
89+
}
90+
91+
92+
}
93+
94+
override def beforeAll: Unit = BookDAO.drop().headResult()
95+
96+
}

0 commit comments

Comments
 (0)