Example problem to solve
One of the most popular class in our services is User
.
The user may enter his nickname
during registration.
Let’s assume that our business requirement is:
- user should be unique by his nickname
Solution in MongoDB - case insensitive index
If we use MongoDB, we can use unique index with appropriate option to achieve that requirement.
The appropriate option is collation with with set fields locale
and strength
.
Supported values for this fields you can find here:
For this article let’s assume that we want to focus on language English (United States) so we will use en_US
value for locale
.
For strength
we should use values 1
or 2
because this levels means that values comparison will ignore case.
So, our solution directly on MongoDB will look like:
1
db.users.createIndex( { nickname: 1}, { unique: true, collation: { locale: 'en_US', strength: 1 } } )
How to create case insensitive index in MongoDB using Spring Framework?
Usually for creating indexes we can use annotations:
- @Indexed on field
- @CompoundIndex on class
They have option for uniqueness to set but not for collation.
Fortunately, such option is available if we create index directly via MongoTemplate
. So, with such simple code we can meet the requirement.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Configuration
@DependsOn("mongoTemplate")
class CollectionConfig(@Autowired private val mongoTemplate: MongoTemplate) {
@PostConstruct
fun ensureIndexes() {
mongoTemplate.indexOps(User::class.java).ensureIndex(
Index("username", Sort.Direction.ASC)
.unique()
.collation(
of(Locale.US).strength(ComparisonLevel.primary())
)
)
}
}
Issue in spring-boot-mongodb
project
I’ve created issue to add parameters in @Indexed
and @CompoundIndex
annotations for setting collation
value. You can watch this issue if you are interested in what will happen next.
Sources
- Case Insensitive Index in MongoDB documentation.
- Question on StackOverflow with mine answer as well.
Comments powered by Disqus.