Skip to content

Commit 12649f1

Browse files
GH-1862 - Support combining startingWith and endingWith with IgnoreCase in derived queries.
This closes #1862
1 parent 6b3f35f commit 12649f1

File tree

3 files changed

+44
-55
lines changed

3 files changed

+44
-55
lines changed

spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/filter/PropertyComparisonBuilder.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,11 @@
1717

1818
import static org.springframework.data.repository.query.parser.Part.Type.*;
1919

20+
import java.util.Arrays;
2021
import java.util.Collections;
22+
import java.util.HashSet;
2123
import java.util.List;
24+
import java.util.Set;
2225
import java.util.Stack;
2326

2427
import org.neo4j.ogm.cypher.BooleanOperator;
@@ -34,6 +37,17 @@
3437
*/
3538
class PropertyComparisonBuilder extends FilterBuilder {
3639

40+
private static final Set<Part.Type> TYPES_SUPPORTING_IGNORE_CASE;
41+
42+
static {
43+
Set<Part.Type> typesSupportingIgnoreCase = new HashSet<>();
44+
typesSupportingIgnoreCase.add(SIMPLE_PROPERTY);
45+
typesSupportingIgnoreCase.add(CONTAINING);
46+
typesSupportingIgnoreCase.add(STARTING_WITH);
47+
typesSupportingIgnoreCase.add(ENDING_WITH);
48+
TYPES_SUPPORTING_IGNORE_CASE = Collections.unmodifiableSet(typesSupportingIgnoreCase);
49+
}
50+
3751
PropertyComparisonBuilder(Part part, BooleanOperator booleanOperator, Class<?> entityType) {
3852
super(part, booleanOperator, entityType);
3953
}
@@ -128,7 +142,6 @@ private boolean canIgnoreCase(Part part) {
128142
}
129143

130144
private boolean isSupportedIgnoreKeyword(Part part) {
131-
Part.Type type = part.getType();
132-
return type == SIMPLE_PROPERTY || type == CONTAINING;
145+
return TYPES_SUPPORTING_IGNORE_CASE.contains(part.getType());
133146
}
134147
}

spring-data-neo4j/src/test/java/org/springframework/data/neo4j/examples/restaurants/RestaurantTests.java

Lines changed: 25 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
import java.util.Collections;
2424
import java.util.Date;
2525
import java.util.List;
26+
import java.util.Locale;
27+
import java.util.function.Supplier;
2628

2729
import org.junit.After;
2830
import org.junit.Test;
@@ -374,78 +376,59 @@ public void shouldFindByLaunchDateAfter() {
374376
assertThat(results.size()).isEqualTo(0);
375377
}
376378

377-
/**
378-
* All findByPropertyLike does currently is to require an exact match, ignoring case.
379-
*/
380-
@Test // DATAGRAPH-904
381-
public void shouldFindByNameNotLike() {
382-
379+
void runTestThatShouldReturnOnlySFO(Supplier<List<Restaurant>> restaurantSupplier) {
383380
Restaurant restaurant = new Restaurant("San Francisco International Airport (SFO)", 68.0);
384381
restaurantRepository.save(restaurant);
385382

386383
Restaurant kuroda = new Restaurant("Kuroda", 72.4);
387384
restaurantRepository.save(kuroda);
388385

389-
List<Restaurant> results = restaurantRepository.findByNameNotLike("kuroda");
386+
List<Restaurant> results = restaurantSupplier.get();
390387
assertNotNull(results);
391-
assertThat(results.size()).isEqualTo(1);
392-
assertThat(results.get(0).getName())
393-
.isEqualTo("San Francisco International Airport (SFO)");
394-
388+
assertThat(results).extracting(Restaurant::getName).containsExactly("San Francisco International Airport (SFO)");
395389
}
396390

397391
/**
398392
* All findByPropertyLike does currently is to require an exact match, ignoring case.
399393
*/
400394
@Test // DATAGRAPH-904
401-
public void shouldFindByNameLike() {
402-
403-
Restaurant restaurant = new Restaurant("San Francisco International Airport (SFO)", 68.0);
404-
restaurantRepository.save(restaurant);
395+
public void shouldFindByNameNotLike() {
405396

406-
Restaurant kuroda = new Restaurant("Kuroda", 72.4);
407-
restaurantRepository.save(kuroda);
397+
runTestThatShouldReturnOnlySFO(() -> restaurantRepository.findByNameNotLike("kuroda"));
398+
}
408399

409-
List<Restaurant> results = restaurantRepository.findByNameLike("*san francisco international*");
410-
assertNotNull(results);
411-
assertThat(results.size()).isEqualTo(1);
412-
assertThat(results.get(0).getName())
413-
.isEqualTo("San Francisco International Airport (SFO)");
400+
/**
401+
* All findByPropertyLike does currently is to require an exact match, ignoring case.
402+
*/
403+
@Test // DATAGRAPH-904
404+
public void shouldFindByNameLike() {
414405

406+
runTestThatShouldReturnOnlySFO(() -> restaurantRepository.findByNameLike("*san francisco international*"));
415407
}
416408

417409
@Test // DATAGRAPH-904
418410
public void shouldFindByNameStartingWith() {
419411

420-
Restaurant restaurant = new Restaurant("San Francisco International Airport (SFO)", 68.0);
421-
restaurantRepository.save(restaurant);
412+
runTestThatShouldReturnOnlySFO(() -> restaurantRepository.findByNameStartingWith("San Francisco"));
422413

423-
Restaurant kuroda = new Restaurant("Kuroda", 72.4);
424-
restaurantRepository.save(kuroda);
414+
}
425415

426-
List<Restaurant> results = restaurantRepository.findByNameStartingWith("San Francisco");
427-
assertNotNull(results);
428-
assertThat(results.size()).isEqualTo(1);
429-
assertThat(results.get(0).getName())
430-
.isEqualTo("San Francisco International Airport (SFO)");
416+
@Test // DATAGRAPH-1862
417+
public void shouldFindByNameStartingWithIgnoringCase() {
431418

419+
runTestThatShouldReturnOnlySFO(() -> restaurantRepository.findByNameStartingWithIgnoreCase("San Francisco".toLowerCase(Locale.ROOT)));
432420
}
433421

434422
@Test // DATAGRAPH-904
435423
public void shouldFindByNameEndingWith() {
436424

437-
Restaurant restaurant = new Restaurant("San Francisco International Airport (SFO)", 68.0);
438-
restaurantRepository.save(restaurant);
439-
440-
Restaurant kuroda = new Restaurant("Kuroda", 72.4);
441-
restaurantRepository.save(kuroda);
425+
runTestThatShouldReturnOnlySFO(() -> restaurantRepository.findByNameEndingWith("Airport (SFO)"));
426+
}
442427

443-
List<Restaurant> results = restaurantRepository.findByNameEndingWith("Airport (SFO)");
444-
assertNotNull(results);
445-
assertThat(results.size()).isEqualTo(1);
446-
assertThat(results.get(0).getName())
447-
.isEqualTo("San Francisco International Airport (SFO)");
428+
@Test // DATAGRAPH-1862
429+
public void shouldFindByNameEndingWithIgnoringCase() {
448430

431+
runTestThatShouldReturnOnlySFO(() -> restaurantRepository.findByNameEndingWithIgnoreCase("Airport (SFO)".toLowerCase(Locale.ROOT)));
449432
}
450433

451434
@Test // DATAGRAPH-904
@@ -522,18 +505,7 @@ public void shouldFindByNameIn() {
522505
@Test // DATAGRAPH-904
523506
public void shouldFindByNameMatchesRegEx() {
524507

525-
Restaurant restaurant = new Restaurant("San Francisco International Airport (SFO)", 68.0);
526-
restaurantRepository.save(restaurant);
527-
528-
Restaurant kuroda = new Restaurant("Kuroda", 72.4);
529-
restaurantRepository.save(kuroda);
530-
531-
List<Restaurant> results = restaurantRepository.findByNameMatchesRegex("(?i)san francisco.*");
532-
assertNotNull(results);
533-
assertThat(results.size()).isEqualTo(1);
534-
assertThat(results.get(0).getName())
535-
.isEqualTo("San Francisco International Airport (SFO)");
536-
508+
runTestThatShouldReturnOnlySFO(() -> restaurantRepository.findByNameMatchesRegex("(?i)san francisco.*"));
537509
}
538510

539511
@Test // DATAGRAPH-904

spring-data-neo4j/src/test/java/org/springframework/data/neo4j/examples/restaurants/repo/RestaurantRepository.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,12 @@ public interface RestaurantRepository extends Neo4jRepository<Restaurant, Long>
6161

6262
List<Restaurant> findByNameStartingWith(String string);
6363

64+
List<Restaurant> findByNameStartingWithIgnoreCase(String string);
65+
6466
List<Restaurant> findByNameEndingWith(String string);
6567

68+
List<Restaurant> findByNameEndingWithIgnoreCase(String string);
69+
6670
List<Restaurant> findByNameContaining(String string);
6771

6872
List<Restaurant> findByNameNotContaining(String string);

0 commit comments

Comments
 (0)