From 303a057d8637e592a3bf255324c0cc56b326bfc4 Mon Sep 17 00:00:00 2001 From: Andrew Duncan Date: Tue, 25 Jun 2013 18:02:15 +0200 Subject: [PATCH] DATAMONGO-701 - Improve performance of starts-with and ends-with queries. This changes the starts-with regex to the prefixed form using ^ to better make use of any index on the queried field. Also changes ending-with queries to use the $ anchor. --- .../repository/query/MongoQueryCreator.java | 21 +++++++------- ...tractPersonRepositoryIntegrationTests.java | 28 ++++++++++++++++--- .../mongodb/repository/PersonRepository.java | 4 +++ .../query/MongoQueryCreatorUnitTests.java | 4 +-- 4 files changed, 41 insertions(+), 16 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryCreator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryCreator.java index 978cebe3a..2ba8a6b47 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryCreator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryCreator.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2012 the original author or authors. + * Copyright 2010-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -268,15 +268,16 @@ class MongoQueryCreator extends AbstractQueryCreator { private String toLikeRegex(String source, Type type) { switch (type) { - case STARTING_WITH: - source = source + "*"; - break; - case ENDING_WITH: - source = "*" + source; - break; - case CONTAINING: - source = "*" + source + "*"; - break; + case STARTING_WITH: + source = "^" + source; + break; + case ENDING_WITH: + source = source + "$"; + break; + case CONTAINING: + source = "*" + source + "*"; + break; + default: } return source.replaceAll("\\*", ".*"); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java index 74f5460db..174ba5e06 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java @@ -53,11 +53,9 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) public abstract class AbstractPersonRepositoryIntegrationTests { - @Autowired - protected PersonRepository repository; + @Autowired protected PersonRepository repository; - @Autowired - MongoOperations operations; + @Autowired MongoOperations operations; Person dave, oliver, carter, boyd, stefan, leroi, alicia; QPerson person; @@ -546,4 +544,26 @@ public abstract class AbstractPersonRepositoryIntegrationTests { assertThat(result, hasSize(1)); assertThat(result, hasItem(dave)); } + + /** + * @see DATAMONGO-701 + */ + @Test + public void executesDerivedStartsWithQueryCorrectly() { + + List result = repository.findByLastnameStartsWith("Matt"); + assertThat(result, hasSize(2)); + assertThat(result, hasItems(dave, oliver)); + } + + /** + * @see DATAMONGO-701 + */ + @Test + public void executesDerivedEndsWithQueryCorrectly() { + + List result = repository.findByLastnameEndsWith("thews"); + assertThat(result, hasSize(2)); + assertThat(result, hasItems(dave, oliver)); + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java index 7b7424055..ff723d881 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java @@ -47,6 +47,10 @@ public interface PersonRepository extends MongoRepository, Query */ List findByLastname(String lastname); + List findByLastnameStartsWith(String prefix); + + List findByLastnameEndsWith(String postfix); + /** * Returns all {@link Person}s with the given lastname ordered by their firstname. * diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java index 0b1ffabe4..e46caee89 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java @@ -263,7 +263,7 @@ public class MongoQueryCreatorUnitTests { MongoQueryCreator creator = new MongoQueryCreator(tree, getAccessor(converter, "Matt"), context); Query query = creator.createQuery(); - assertThat(query, is(query(where("foo").regex("Matt.*")))); + assertThat(query, is(query(where("foo").regex("^Matt")))); } /** @@ -276,7 +276,7 @@ public class MongoQueryCreatorUnitTests { MongoQueryCreator creator = new MongoQueryCreator(tree, getAccessor(converter, "ews"), context); Query query = creator.createQuery(); - assertThat(query, is(query(where("foo").regex(".*ews")))); + assertThat(query, is(query(where("foo").regex("ews$")))); } /**