Skip to content

Commit 90fb286

Browse files
committed
DATACOUCH-588 - Part 2 of framework changes. Add support for projection and distinct.
Support for projection is only for properties of the top-level entity. For instance, in UserSubmission, only the properties below can be specified in the projection. Projection support does not provide means of specifying something like address.street - you can only project (or not project) the whole address property. However, the address type in your resultType could have a subset of the properties in Address. If the corresponding submissions in the resultType contained only the userId property public class UserSubmission extends ComparableEntity { private String id; private String username; private List<String> roles; private Address address; private List<Submission> submissions; Support for Distinct - I have appropriated the MongoDB model for Distinct. It defines a separate DistinctOperationSupport class (within ExecutableFindByQuerySupport) which supports the distinct( distinctFields ) api and execution. The DistinctOperationSupport class has only a distinctFields member, and a 'delegate' member, which is an ExecutableFindByQuerySupport object. TBH, I don't see the advantage over simply adding a distinctFields member to ExecutableFindByQuerySupport Amend #1 - changes as discussed in Pull Request - clean up test entity types Amend #2 - Eliminate DistinctOperationSupport class. In MongoDB, only distinct on a single field is supported, so the returnType from distinct was very different from the returnType of other query operations (all(), one() etc. (but so is count(), and it doesn't need it's own class)). In Couchbase, distinct on any fields in the entity is allowed - so the returned type could be the domainType or resultType. And as(resultType) still allows any resultType to be specified. This makes it unnecessary to have combinations of interfaces such as DistinctWithProjection and DistinctWithQuery. - Clean up the interfaces in ExecutableFindByQuery. There are two types of interfaces (a) the TerminatingFindByQuery which has the one(), oneValue() first(), firstValue(), all(), count(), exists() and stream(); and (b) the option interfaces (FindByQueryWithConsistency etc), which are essentially with-er interfaces. The changes are: 1) make all the with-er interfaces base interfaces instead of chaining them together. (I don't know why there isn't simply one interface with all the with-er methods). 2) make the ExecutableFindByQuery interface extend the Terminating interface and all the with-er interfaces. Amend #3 - Add execution support for collections Amend #4 - Add tests for collections. This includes a new CollectionAwareIntegrationTests class which extends a new JavaIntegratationTests class which extends the existing ClusterAwareIntegrationTests. - Fixed up several issues collections issues that were uncovered by the tests. - Did further cleanup of OperationSupport interfaces. Amend #5 - Revert changes to interfaces in *Operation - Sorted interfaces in same order for consistency (because of the chaining of interfaces, fluent methods must be called in order).
1 parent 3364e0f commit 90fb286

File tree

63 files changed

+2282
-519
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+2282
-519
lines changed

pom.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,14 @@
197197
<version>${kotlin}</version>
198198
<scope>test</scope>
199199
</dependency>
200+
201+
<dependency>
202+
<groupId>org.awaitility</groupId>
203+
<artifactId>awaitility</artifactId>
204+
<version>4.0.3</version>
205+
<scope>test</scope>
206+
</dependency>
207+
200208
</dependencies>
201209

202210
<repositories>

src/main/java/org/springframework/data/couchbase/core/ExecutableFindByAnalyticsOperation.java

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@
1919
import java.util.Optional;
2020
import java.util.stream.Stream;
2121

22-
import com.couchbase.client.java.analytics.AnalyticsScanConsistency;
23-
import com.couchbase.client.java.query.QueryScanConsistency;
2422
import org.springframework.dao.IncorrectResultSizeDataAccessException;
2523
import org.springframework.data.couchbase.core.query.AnalyticsQuery;
2624
import org.springframework.lang.Nullable;
2725

26+
import com.couchbase.client.java.analytics.AnalyticsScanConsistency;
27+
2828
public interface ExecutableFindByAnalyticsOperation {
2929

3030
/**
@@ -114,17 +114,30 @@ interface FindByAnalyticsWithQuery<T> extends TerminatingFindByAnalytics<T> {
114114

115115
}
116116

117+
@Deprecated
117118
interface FindByAnalyticsConsistentWith<T> extends FindByAnalyticsWithQuery<T> {
118119

119120
/**
120121
* Allows to override the default scan consistency.
121122
*
122123
* @param scanConsistency the custom scan consistency to use for this analytics query.
123124
*/
125+
@Deprecated
124126
FindByAnalyticsWithQuery<T> consistentWith(AnalyticsScanConsistency scanConsistency);
125127

126128
}
127129

128-
interface ExecutableFindByAnalytics<T> extends FindByAnalyticsConsistentWith<T> {}
130+
interface FindByAnalyticsWithConsistency<T> extends FindByAnalyticsConsistentWith<T> {
131+
132+
/**
133+
* Allows to override the default scan consistency.
134+
*
135+
* @param scanConsistency the custom scan consistency to use for this analytics query.
136+
*/
137+
FindByAnalyticsConsistentWith<T> withConsistency(AnalyticsScanConsistency scanConsistency);
138+
139+
}
140+
141+
interface ExecutableFindByAnalytics<T> extends FindByAnalyticsWithConsistency<T> {}
129142

130143
}

src/main/java/org/springframework/data/couchbase/core/ExecutableFindByAnalyticsOperationSupport.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,10 @@
1515
*/
1616
package org.springframework.data.couchbase.core;
1717

18-
import org.springframework.data.couchbase.core.ReactiveFindByAnalyticsOperationSupport.ReactiveFindByAnalyticsSupport;
19-
2018
import java.util.List;
2119
import java.util.stream.Stream;
2220

21+
import org.springframework.data.couchbase.core.ReactiveFindByAnalyticsOperationSupport.ReactiveFindByAnalyticsSupport;
2322
import org.springframework.data.couchbase.core.query.AnalyticsQuery;
2423

2524
import com.couchbase.client.java.analytics.AnalyticsScanConsistency;
@@ -79,10 +78,16 @@ public TerminatingFindByAnalytics<T> matching(final AnalyticsQuery query) {
7978
}
8079

8180
@Override
81+
@Deprecated
8282
public FindByAnalyticsWithQuery<T> consistentWith(final AnalyticsScanConsistency scanConsistency) {
8383
return new ExecutableFindByAnalyticsSupport<>(template, domainType, query, scanConsistency);
8484
}
8585

86+
@Override
87+
public FindByAnalyticsWithConsistency<T> withConsistency(final AnalyticsScanConsistency scanConsistency) {
88+
return new ExecutableFindByAnalyticsSupport<>(template, domainType, query, scanConsistency);
89+
}
90+
8691
@Override
8792
public Stream<T> stream() {
8893
return reactiveSupport.all().toStream();

src/main/java/org/springframework/data/couchbase/core/ExecutableFindByIdOperationSupport.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,11 @@
1515
*/
1616
package org.springframework.data.couchbase.core;
1717

18-
import org.springframework.data.couchbase.core.ReactiveFindByIdOperationSupport.ReactiveFindByIdSupport;
19-
2018
import java.util.Arrays;
2119
import java.util.Collection;
2220
import java.util.List;
2321

22+
import org.springframework.data.couchbase.core.ReactiveFindByIdOperationSupport.ReactiveFindByIdSupport;
2423
import org.springframework.util.Assert;
2524

2625
public class ExecutableFindByIdOperationSupport implements ExecutableFindByIdOperation {

src/main/java/org/springframework/data/couchbase/core/ExecutableFindByQueryOperation.java

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import org.springframework.dao.IncorrectResultSizeDataAccessException;
2323
import org.springframework.data.couchbase.core.query.Query;
24+
import org.springframework.data.couchbase.core.query.QueryCriteriaDefinition;
2425
import org.springframework.lang.Nullable;
2526

2627
import com.couchbase.client.java.query.QueryScanConsistency;
@@ -117,30 +118,92 @@ interface FindByQueryWithQuery<T> extends TerminatingFindByQuery<T> {
117118
*/
118119
TerminatingFindByQuery<T> matching(Query query);
119120

121+
/**
122+
* Set the filter {@link QueryCriteriaDefinition criteria} to be used.
123+
*
124+
* @param criteria must not be {@literal null}.
125+
* @return new instance of {@link ExecutableFindByQuery}.
126+
* @throws IllegalArgumentException if criteria is {@literal null}.
127+
*/
128+
default TerminatingFindByQuery<T> matching(QueryCriteriaDefinition criteria) {
129+
return matching(Query.query(criteria));
130+
}
131+
120132
}
121133

134+
@Deprecated
122135
interface FindByQueryConsistentWith<T> extends FindByQueryWithQuery<T> {
123136

124137
/**
125138
* Allows to override the default scan consistency.
126139
*
127140
* @param scanConsistency the custom scan consistency to use for this query.
128141
*/
129-
FindByQueryConsistentWith<T> consistentWith(QueryScanConsistency scanConsistency);
142+
@Deprecated
143+
FindByQueryWithQuery<T> consistentWith(QueryScanConsistency scanConsistency);
144+
145+
}
146+
147+
interface FindByQueryWithConsistency<T> extends FindByQueryConsistentWith<T> {
148+
149+
/**
150+
* Allows to override the default scan consistency.
151+
*
152+
* @param scanConsistency the custom scan consistency to use for this query.
153+
*/
154+
FindByQueryConsistentWith<T> withConsistency(QueryScanConsistency scanConsistency);
130155

131156
}
132157

133-
interface FindByQueryInCollection<T> extends FindByQueryConsistentWith<T> {
158+
interface FindByQueryInCollection<T> extends FindByQueryWithConsistency<T> {
134159

135160
/**
136161
* Allows to override the default scan consistency.
137162
*
138163
* @param collection the collection to use for this query.
139164
*/
140-
FindByQueryInCollection<T> inCollection(String collection);
165+
FindByQueryWithConsistency<T> inCollection(String collection);
141166

142167
}
143168

144-
interface ExecutableFindByQuery<T> extends FindByQueryInCollection<T> {}
169+
/**
170+
* Result type override (Optional).
171+
*/
172+
interface FindByQueryWithProjection<T> extends FindByQueryInCollection<T> {
173+
174+
/**
175+
* Define the target type fields should be mapped to. <br />
176+
* Skip this step if you are anyway only interested in the original domain type.
177+
*
178+
* @param resturnType must not be {@literal null}.
179+
* @param <R> result type.
180+
* @return new instance of {@link FindByQueryWithProjection}.
181+
* @throws IllegalArgumentException if resturnType is {@literal null}.
182+
*/
183+
<R> FindByQueryInCollection<R> as(Class<R> resturnType);
184+
185+
}
186+
187+
/**
188+
* Distinct Find support.
189+
*/
190+
interface FindByQueryWithDistinct<T> extends FindByQueryWithProjection<T> {
191+
192+
/**
193+
* Finds the distinct values for a specified {@literal field} across a single collection
194+
*
195+
* @param distinctFields name of the field. Must not be {@literal null}.
196+
* @return new instance of {@link ExecutableFindByQuery}.
197+
* @throws IllegalArgumentException if field is {@literal null}.
198+
*/
199+
FindByQueryWithProjection<T> distinct(String[] distinctFields);
200+
201+
}
202+
203+
/**
204+
* {@link ExecutableFindByQuery} provides methods for constructing lookup operations in a fluent way.
205+
*/
206+
207+
interface ExecutableFindByQuery<T> extends FindByQueryWithDistinct<T> {}
145208

146209
}

src/main/java/org/springframework/data/couchbase/core/ExecutableFindByQueryOperationSupport.java

Lines changed: 45 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import org.springframework.data.couchbase.core.ReactiveFindByQueryOperationSupport.ReactiveFindByQuerySupport;
2222
import org.springframework.data.couchbase.core.query.Query;
23+
import org.springframework.util.Assert;
2324

2425
import com.couchbase.client.java.query.QueryScanConsistency;
2526

@@ -41,28 +42,33 @@ public ExecutableFindByQueryOperationSupport(final CouchbaseTemplate template) {
4142

4243
@Override
4344
public <T> ExecutableFindByQuery<T> findByQuery(final Class<T> domainType) {
44-
return new ExecutableFindByQuerySupport<>(template, domainType, ALL_QUERY, QueryScanConsistency.NOT_BOUNDED,
45-
"_default._default");
45+
return new ExecutableFindByQuerySupport<T>(template, domainType, domainType, ALL_QUERY,
46+
QueryScanConsistency.NOT_BOUNDED, null, null);
4647
}
4748

4849
static class ExecutableFindByQuerySupport<T> implements ExecutableFindByQuery<T> {
4950

5051
private final CouchbaseTemplate template;
51-
private final Class<T> domainType;
52+
private final Class<?> domainType;
53+
private final Class<T> returnType;
5254
private final Query query;
5355
private final ReactiveFindByQuerySupport<T> reactiveSupport;
5456
private final QueryScanConsistency scanConsistency;
5557
private final String collection;
58+
private final String[] distinctFields;
5659

57-
ExecutableFindByQuerySupport(final CouchbaseTemplate template, final Class<T> domainType, final Query query,
58-
final QueryScanConsistency scanConsistency, final String collection) {
60+
ExecutableFindByQuerySupport(final CouchbaseTemplate template, final Class<?> domainType, final Class<T> returnType,
61+
final Query query, final QueryScanConsistency scanConsistency, final String collection,
62+
final String[] distinctFields) {
5963
this.template = template;
6064
this.domainType = domainType;
65+
this.returnType = returnType;
6166
this.query = query;
62-
this.reactiveSupport = new ReactiveFindByQuerySupport<T>(template.reactive(), domainType, query, scanConsistency,
63-
collection);
67+
this.reactiveSupport = new ReactiveFindByQuerySupport<T>(template.reactive(), domainType, returnType, query,
68+
scanConsistency, collection, distinctFields);
6469
this.scanConsistency = scanConsistency;
6570
this.collection = collection;
71+
this.distinctFields = distinctFields;
6672
}
6773

6874
@Override
@@ -88,17 +94,44 @@ public TerminatingFindByQuery<T> matching(final Query query) {
8894
} else {
8995
scanCons = scanConsistency;
9096
}
91-
return new ExecutableFindByQuerySupport<>(template, domainType, query, scanCons, collection);
97+
return new ExecutableFindByQuerySupport<>(template, domainType, returnType, query, scanCons, collection,
98+
distinctFields);
9299
}
93100

94101
@Override
95-
public FindByQueryConsistentWith<T> consistentWith(final QueryScanConsistency scanConsistency) {
96-
return new ExecutableFindByQuerySupport<>(template, domainType, query, scanConsistency, collection);
102+
@Deprecated
103+
public FindByQueryWithQuery<T> consistentWith(final QueryScanConsistency scanConsistency) {
104+
return new ExecutableFindByQuerySupport<>(template, domainType, returnType, query, scanConsistency, collection,
105+
distinctFields);
97106
}
98107

99108
@Override
100-
public FindByQueryInCollection<T> inCollection(final String collection) {
101-
return new ExecutableFindByQuerySupport<>(template, domainType, query, scanConsistency, collection);
109+
public FindByQueryConsistentWith<T> withConsistency(final QueryScanConsistency scanConsistency) {
110+
return new ExecutableFindByQuerySupport<>(template, domainType, returnType, query, scanConsistency, collection,
111+
distinctFields);
112+
}
113+
114+
@Override
115+
public FindByQueryWithConsistency<T> inCollection(final String collection) {
116+
Assert.hasText(collection, "Collection must not be null nor empty.");
117+
return new ExecutableFindByQuerySupport<>(template, domainType, returnType, query, scanConsistency, collection,
118+
distinctFields);
119+
}
120+
121+
@Override
122+
public <R> FindByQueryInCollection<R> as(Class<R> resturnType) {
123+
Assert.notNull(resturnType, "returnType must not be null!");
124+
125+
return new ExecutableFindByQuerySupport<R>(template, domainType,
126+
resturnType, query, scanConsistency, collection,
127+
distinctFields);
128+
}
129+
130+
@Override
131+
public FindByQueryWithProjection<T> distinct(String[] distinctFields) {
132+
Assert.notNull(distinctFields, "distinctFields must not be null!");
133+
return new ExecutableFindByQuerySupport<>(template, domainType, returnType, query, scanConsistency, collection,
134+
distinctFields);
102135
}
103136

104137
@Override
@@ -115,7 +148,6 @@ public long count() {
115148
public boolean exists() {
116149
return count() > 0;
117150
}
118-
119151
}
120152

121153
}

src/main/java/org/springframework/data/couchbase/core/ExecutableRemoveByQueryOperation.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,23 @@ interface RemoveByQueryWithQuery<T> extends TerminatingRemoveByQuery<T> {
3737

3838
}
3939

40+
@Deprecated
4041
interface RemoveByQueryConsistentWith<T> extends RemoveByQueryWithQuery<T> {
4142

43+
@Deprecated
4244
RemoveByQueryWithQuery<T> consistentWith(QueryScanConsistency scanConsistency);
4345

4446
}
4547

46-
interface RemoveByQueryInCollection<T> extends RemoveByQueryConsistentWith<T> {
48+
interface RemoveByQueryWithConsistency<T> extends RemoveByQueryConsistentWith<T> {
4749

48-
RemoveByQueryConsistentWith<T> inCollection(String collection);
50+
RemoveByQueryConsistentWith<T> withConsistency(QueryScanConsistency scanConsistency);
51+
52+
}
53+
54+
interface RemoveByQueryInCollection<T> extends RemoveByQueryWithConsistency<T> {
55+
56+
RemoveByQueryWithConsistency<T> inCollection(String collection);
4957

5058
}
5159

src/main/java/org/springframework/data/couchbase/core/ExecutableRemoveByQueryOperationSupport.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.springframework.data.couchbase.core.query.Query;
2222

2323
import com.couchbase.client.java.query.QueryScanConsistency;
24+
import org.springframework.util.Assert;
2425

2526
public class ExecutableRemoveByQueryOperationSupport implements ExecutableRemoveByQueryOperation {
2627

@@ -35,7 +36,7 @@ public ExecutableRemoveByQueryOperationSupport(final CouchbaseTemplate template)
3536
@Override
3637
public <T> ExecutableRemoveByQuery<T> removeByQuery(Class<T> domainType) {
3738
return new ExecutableRemoveByQuerySupport<>(template, domainType, ALL_QUERY, QueryScanConsistency.NOT_BOUNDED,
38-
"_default._default");
39+
null);
3940
}
4041

4142
static class ExecutableRemoveByQuerySupport<T> implements ExecutableRemoveByQuery<T> {
@@ -69,12 +70,19 @@ public TerminatingRemoveByQuery<T> matching(final Query query) {
6970
}
7071

7172
@Override
73+
@Deprecated
7274
public RemoveByQueryWithQuery<T> consistentWith(final QueryScanConsistency scanConsistency) {
7375
return new ExecutableRemoveByQuerySupport<>(template, domainType, query, scanConsistency, collection);
7476
}
7577

7678
@Override
77-
public RemoveByQueryInCollection<T> inCollection(final String collection) {
79+
public RemoveByQueryConsistentWith<T> withConsistency(final QueryScanConsistency scanConsistency) {
80+
return new ExecutableRemoveByQuerySupport<>(template, domainType, query, scanConsistency, collection);
81+
}
82+
83+
@Override
84+
public RemoveByQueryWithConsistency<T> inCollection(final String collection) {
85+
Assert.hasText(collection, "Collection must not be null nor empty.");
7886
return new ExecutableRemoveByQuerySupport<>(template, domainType, query, scanConsistency, collection);
7987
}
8088

0 commit comments

Comments
 (0)