Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>5.1.0-SNAPSHOT</version>
<version>5.1.x-GH-5123-SNAPSHOT</version>
<packaging>pom</packaging>

<name>Spring Data MongoDB</name>
Expand Down
2 changes: 1 addition & 1 deletion spring-data-mongodb-distribution/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>5.1.0-SNAPSHOT</version>
<version>5.1.x-GH-5123-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion spring-data-mongodb/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>5.1.0-SNAPSHOT</version>
<version>5.1.x-GH-5123-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,26 @@ static RegexPlaceholder regex(int index, @Nullable String options) {
return new RegexPlaceholder(index, options);
}

/**
* Create a placeholder that indicates the value should be treated as list.
*
* @param index zero-based index referring to the bindable method parameter.
* @return new instance of {@link Placeholder}.
*/
static Placeholder asList(int index) {
return asList(indexed(index));
}

/**
* Create a placeholder that indicates the wrapped placeholder should be treated as list.
*
* @param source the target placeholder
* @return new instance of {@link Placeholder}.
*/
static Placeholder asList(Placeholder source) {
return new AsListPlaceholder(source);
}

/**
* A placeholder expression used when rending queries to JSON.
*
Expand Down Expand Up @@ -295,4 +315,17 @@ public String toString() {
}
}

record AsListPlaceholder(Placeholder placeholder) implements Placeholder {

@Override
public String toString() {
return getValue();
}

@Override
public String getValue() {
return "[" + placeholder.getValue() + "]";
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import org.bson.conversions.Bson;
import org.jspecify.annotations.NullUnmarked;
import org.jspecify.annotations.Nullable;

import org.springframework.data.core.TypeInformation;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Range;
Expand All @@ -48,6 +47,7 @@
import org.springframework.data.mongodb.core.query.TextCriteria;
import org.springframework.data.mongodb.core.query.UpdateDefinition;
import org.springframework.data.mongodb.repository.VectorSearch;
import org.springframework.data.mongodb.repository.aot.AotPlaceholders.AsListPlaceholder;
import org.springframework.data.mongodb.repository.aot.AotPlaceholders.Placeholder;
import org.springframework.data.mongodb.repository.aot.AotPlaceholders.RegexPlaceholder;
import org.springframework.data.mongodb.repository.query.ConvertingParameterAccessor;
Expand Down Expand Up @@ -132,6 +132,10 @@ protected Criteria createContainingCriteria(Part part, MongoPersistentProperty p
return criteria.raw("$regex", param);
}

if (param instanceof AsListPlaceholder asListPlaceholder && !property.isCollectionLike()) {
return super.createContainingCriteria(part, property, criteria, asListPlaceholder.placeholder());
}

return super.createContainingCriteria(part, property, criteria, param);
}
}
Expand Down Expand Up @@ -226,7 +230,24 @@ public PlaceholderParameterAccessor(PartTree partTree, QueryMethod queryMethod)
partForIndex.shouldIgnoreCase().equals(IgnoreCaseType.ALWAYS)
|| partForIndex.shouldIgnoreCase().equals(IgnoreCaseType.WHEN_POSSIBLE) ? "i"
: null));
} else {
} else if (partForIndex != null && (partForIndex.getType().equals(Type.IN)
|| partForIndex.getType().equals(Type.NOT_IN) || partForIndex.getType().equals(Type.CONTAINING)
|| partForIndex.getType().equals(Type.NOT_CONTAINING))) {

if (partForIndex.getProperty().isCollection()
&& !TypeInformation.of(parameter.getType()).isCollectionLike()) {
if (partForIndex.shouldIgnoreCase().equals(IgnoreCaseType.ALWAYS)) {
placeholders.add(parameter.getIndex(),
AotPlaceholders.asList(AotPlaceholders.regex(parameter.getIndex(), "i")));
} else {
placeholders.add(parameter.getIndex(), AotPlaceholders.asList(parameter.getIndex()));
}
} else {
placeholders.add(parameter.getIndex(), AotPlaceholders.indexed(parameter.getIndex()));
}
}

else {
placeholders.add(parameter.getIndex(), AotPlaceholders.indexed(parameter.getIndex()));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@

import org.bson.Document;
import org.jspecify.annotations.Nullable;

import org.springframework.data.domain.KeysetScrollPosition;
import org.springframework.data.mongodb.core.query.Collation;
import org.springframework.data.mongodb.core.query.Field;
import org.springframework.data.mongodb.core.query.Meta;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.repository.aot.AotPlaceholders.AsListPlaceholder;
import org.springframework.data.mongodb.repository.aot.AotPlaceholders.RegexPlaceholder;
import org.springframework.util.StringUtils;

Expand Down Expand Up @@ -83,7 +83,7 @@ boolean isRegexPlaceholderAt(int index) {
return false;
}

return this.placeholders.get(index) instanceof RegexPlaceholder;
return obtainAndPotentiallyUnwrapPlaceholder(index) instanceof RegexPlaceholder;
}

@Nullable
Expand All @@ -92,7 +92,21 @@ String getRegexOptions(int index) {
return null;
}

return this.placeholders.get(index) instanceof RegexPlaceholder rgp ? rgp.regexOptions() : null;
Object placeholderValue = obtainAndPotentiallyUnwrapPlaceholder(index);
return placeholderValue instanceof RegexPlaceholder rgp ? rgp.regexOptions() : null;
}

@Nullable Object obtainAndPotentiallyUnwrapPlaceholder(int index) {

if (this.placeholders.isEmpty()) {
return null;
}

Object placeholerValue = this.placeholders.get(index);
if (placeholerValue instanceof AsListPlaceholder asListPlaceholder) {
placeholerValue = asListPlaceholder.placeholder();
}
return placeholerValue;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,9 +195,9 @@ CodeBlock queryParametersCodeBlock() {
String regexOptions = source.getQuery().getRegexOptions(i);

if (StringUtils.hasText(regexOptions)) {
formatted.add(CodeBlock.of("toRegex($L)", parameterName));
} else {
formatted.add(CodeBlock.of("toRegex($L, $S)", parameterName, regexOptions));
} else {
formatted.add(CodeBlock.of("toRegex($L)", parameterName));
}
} else {
formatted.add(CodeBlock.of("$L", parameterName));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1341,6 +1341,20 @@ void findBySkillsContains() {
assertThat(result).hasSize(1).contains(carter);
}

@Test // GH-5123
void findBySkillsContainsSingleElement() {

List<Person> result = repository.findBySkillsContains("Drums");
assertThat(result).hasSize(1).contains(carter);
}

@Test // GH-5123
void findBySkillsContainsSingleElementWithIgnoreCase() {

List<Person> result = repository.findBySkillsContainsIgnoreCase("drums");
assertThat(result).hasSize(1).contains(carter);
}

@Test // DATAMONGO-1425
void findBySkillsNotContains() {

Expand All @@ -1349,6 +1363,14 @@ void findBySkillsNotContains() {
assertThat(result).doesNotContain(carter);
}

@Test // GH-5123
void findBySkillsNotContainsSingleElement() {

List<Person> result = repository.findBySkillsNotContains("Drums");
assertThat(result).hasSize((int) (repository.count() - 1));
assertThat(result).doesNotContain(carter);
}

@Test // DATAMONGO-1424
void findsPersonsByFirstnameNotLike() {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,11 @@ public interface PersonRepository extends MongoRepository<Person, String>, Query
List<Person> findByFirstnameLikeOrderByLastnameAsc(Pattern firstname, Sort sort);

List<Person> findBySkillsContains(List<String> skills);
List<Person> findBySkillsContains(String skill);
List<Person> findBySkillsContainsIgnoreCase(String skill);

List<Person> findBySkillsNotContains(List<String> skills);
List<Person> findBySkillsNotContains(String skill);

@Query("{'age' : { '$lt' : ?0 } }")
List<Person> findByAgeLessThan(int age, Sort sort);
Expand Down
Loading