GH-1862 - Support combining startingWith and endingWith with IgnoreCase in derived queries.

This closes #1862
This commit is contained in:
Michael Simons
2021-01-12 19:14:38 +01:00
parent cc75e026ba
commit fe9b3a4ca3
3 changed files with 43 additions and 48 deletions

View File

@@ -17,8 +17,11 @@ package org.springframework.data.neo4j.repository.query.filter;
import static org.springframework.data.repository.query.parser.Part.Type.*;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.Stack;
import org.neo4j.ogm.cypher.BooleanOperator;
@@ -34,6 +37,17 @@ import org.springframework.util.Assert;
*/
class PropertyComparisonBuilder extends FilterBuilder {
private static final Set<Part.Type> TYPES_SUPPORTING_IGNORE_CASE;
static {
Set<Part.Type> typesSupportingIgnoreCase = new HashSet<>();
typesSupportingIgnoreCase.add(SIMPLE_PROPERTY);
typesSupportingIgnoreCase.add(CONTAINING);
typesSupportingIgnoreCase.add(STARTING_WITH);
typesSupportingIgnoreCase.add(ENDING_WITH);
TYPES_SUPPORTING_IGNORE_CASE = Collections.unmodifiableSet(typesSupportingIgnoreCase);
}
PropertyComparisonBuilder(Part part, BooleanOperator booleanOperator, Class<?> entityType) {
super(part, booleanOperator, entityType);
}
@@ -128,7 +142,6 @@ class PropertyComparisonBuilder extends FilterBuilder {
}
private boolean isSupportedIgnoreKeyword(Part part) {
Part.Type type = part.getType();
return type == SIMPLE_PROPERTY || type == CONTAINING;
return TYPES_SUPPORTING_IGNORE_CASE.contains(part.getType());
}
}

View File

@@ -22,6 +22,8 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.function.Supplier;
import org.junit.After;
import org.junit.Test;
@@ -370,23 +372,26 @@ public class RestaurantTests {
assertEquals(0, results.size());
}
/**
* All findByPropertyLike does currently is to require an exact match, ignoring case.
*/
@Test // DATAGRAPH-904
public void shouldFindByNameNotLike() {
void runTestThatShouldReturnOnlySFO(Supplier<List<Restaurant>> restaurantSupplier) {
Restaurant restaurant = new Restaurant("San Francisco International Airport (SFO)", 68.0);
restaurantRepository.save(restaurant);
Restaurant kuroda = new Restaurant("Kuroda", 72.4);
restaurantRepository.save(kuroda);
List<Restaurant> results = restaurantRepository.findByNameNotLike("kuroda");
List<Restaurant> results = restaurantSupplier.get();
assertNotNull(results);
assertEquals(1, results.size());
assertEquals("San Francisco International Airport (SFO)", results.get(0).getName());
}
/**
* All findByPropertyLike does currently is to require an exact match, ignoring case.
*/
@Test // DATAGRAPH-904
public void shouldFindByNameNotLike() {
runTestThatShouldReturnOnlySFO(() -> restaurantRepository.findByNameNotLike("kuroda"));
}
/**
@@ -395,49 +400,32 @@ public class RestaurantTests {
@Test // DATAGRAPH-904
public void shouldFindByNameLike() {
Restaurant restaurant = new Restaurant("San Francisco International Airport (SFO)", 68.0);
restaurantRepository.save(restaurant);
Restaurant kuroda = new Restaurant("Kuroda", 72.4);
restaurantRepository.save(kuroda);
List<Restaurant> results = restaurantRepository.findByNameLike("*san francisco international*");
assertNotNull(results);
assertEquals(1, results.size());
assertEquals("San Francisco International Airport (SFO)", results.get(0).getName());
runTestThatShouldReturnOnlySFO(() -> restaurantRepository.findByNameLike("*san francisco international*"));
}
@Test // DATAGRAPH-904
public void shouldFindByNameStartingWith() {
Restaurant restaurant = new Restaurant("San Francisco International Airport (SFO)", 68.0);
restaurantRepository.save(restaurant);
runTestThatShouldReturnOnlySFO(() -> restaurantRepository.findByNameStartingWith("San Francisco"));
Restaurant kuroda = new Restaurant("Kuroda", 72.4);
restaurantRepository.save(kuroda);
}
List<Restaurant> results = restaurantRepository.findByNameStartingWith("San Francisco");
assertNotNull(results);
assertEquals(1, results.size());
assertEquals("San Francisco International Airport (SFO)", results.get(0).getName());
@Test // DATAGRAPH-1862
public void shouldFindByNameStartingWithIgnoringCase() {
runTestThatShouldReturnOnlySFO(() -> restaurantRepository.findByNameStartingWithIgnoreCase("San Francisco".toLowerCase(Locale.ROOT)));
}
@Test // DATAGRAPH-904
public void shouldFindByNameEndingWith() {
Restaurant restaurant = new Restaurant("San Francisco International Airport (SFO)", 68.0);
restaurantRepository.save(restaurant);
runTestThatShouldReturnOnlySFO(() -> restaurantRepository.findByNameEndingWith("Airport (SFO)"));
}
Restaurant kuroda = new Restaurant("Kuroda", 72.4);
restaurantRepository.save(kuroda);
List<Restaurant> results = restaurantRepository.findByNameEndingWith("Airport (SFO)");
assertNotNull(results);
assertEquals(1, results.size());
assertEquals("San Francisco International Airport (SFO)", results.get(0).getName());
@Test // DATAGRAPH-1862
public void shouldFindByNameEndingWithIgnoringCase() {
runTestThatShouldReturnOnlySFO(() -> restaurantRepository.findByNameEndingWithIgnoreCase("Airport (SFO)".toLowerCase(Locale.ROOT)));
}
@Test // DATAGRAPH-904
@@ -510,17 +498,7 @@ public class RestaurantTests {
@Test // DATAGRAPH-904
public void shouldFindByNameMatchesRegEx() {
Restaurant restaurant = new Restaurant("San Francisco International Airport (SFO)", 68.0);
restaurantRepository.save(restaurant);
Restaurant kuroda = new Restaurant("Kuroda", 72.4);
restaurantRepository.save(kuroda);
List<Restaurant> results = restaurantRepository.findByNameMatchesRegex("(?i)san francisco.*");
assertNotNull(results);
assertEquals(1, results.size());
assertEquals("San Francisco International Airport (SFO)", results.get(0).getName());
runTestThatShouldReturnOnlySFO(() -> restaurantRepository.findByNameMatchesRegex("(?i)san francisco.*"));
}
@Test // DATAGRAPH-904

View File

@@ -61,8 +61,12 @@ public interface RestaurantRepository extends Neo4jRepository<Restaurant, Long>
List<Restaurant> findByNameStartingWith(String string);
List<Restaurant> findByNameStartingWithIgnoreCase(String string);
List<Restaurant> findByNameEndingWith(String string);
List<Restaurant> findByNameEndingWithIgnoreCase(String string);
List<Restaurant> findByNameContaining(String string);
List<Restaurant> findByNameNotContaining(String string);