Collection support for predicates on meta fields. (#1338)

When a derived query is being created and there is a predicate on
a meta-field ( meta().id, cas, expiry), translate that field
(i.e. id -> meta().id) *without* the bucket or collection name,
as it might apply to a collelction which we do not know yet
(for instance, if there is a withCollection() specified)..
This is fine, because in a derived query, meta() without the
bucket or collection name is unambigous.
This commit is contained in:
Michael Reiche
2022-02-14 09:09:09 -08:00
committed by Michael Reiche
parent 9048c7ca82
commit 6ebb0dd20e
4 changed files with 36 additions and 11 deletions

View File

@@ -76,7 +76,7 @@ public class N1qlQueryCreator extends AbstractQueryCreator<Query, QueryCriteria>
protected QueryCriteria create(final Part part, final Iterator<Object> iterator) {
PersistentPropertyPath<CouchbasePersistentProperty> path = context.getPersistentPropertyPath(part.getProperty());
CouchbasePersistentProperty property = path.getLeafProperty();
return from(part, property, where(addMetaIfRequired(bucketName, path, property, entity)), iterator);
return from(part, property, where(addMetaIfRequired(null, path, property, entity)), iterator);
}
@Override
@@ -187,17 +187,28 @@ public class N1qlQueryCreator extends AbstractQueryCreator<Query, QueryCriteria>
}
}
/**
* Translate meta-fields to META(bucketName).id, cas, expiry.<br>
* If bucketName is null, META().id etc, <br>
* If not a meta-field, just create the corresponding path
*
* @param bucketName
* @param persistentPropertyPath
* @param property
* @param entity
* @return N1QLExpression
*/
public static N1QLExpression addMetaIfRequired(String bucketName,
final PersistentPropertyPath<CouchbasePersistentProperty> persistentPropertyPath,
final CouchbasePersistentProperty property, final PersistentEntity entity) {
if (entity != null && property == entity.getIdProperty()) {
return path(meta(i(bucketName)), i(META_ID_PROPERTY));
return path(meta(bucketName != null ? i(bucketName) : x("")), i(META_ID_PROPERTY));
}
if (property == entity.getVersionProperty()) {
return path(meta(i(bucketName)), i(META_CAS_PROPERTY));
return path(meta(bucketName != null ? i(bucketName) : x("")), i(META_CAS_PROPERTY));
}
if (property.isExpirationProperty()) {
return path(meta(i(bucketName)), i(META_EXPIRATION_PROPERTY));
return path(meta(bucketName != null ? i(bucketName) : x("")), i(META_EXPIRATION_PROPERTY));
}
return x(persistentPropertyPath.toDotPath(cvtr));
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2020 the original author or authors
* Copyright 2012-2022 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.
@@ -40,10 +40,13 @@ public interface UserColRepository extends CouchbaseRepository<UserCol, String>,
// CouchbaseRepositoryQueryCollectionIntegrationTests.testScopeCollectionAnnotationSwap() relies on this
// being commented out.
//<S extends UserCol> S save(S var1);
// <S extends UserCol> S save(S var1);
List<UserCol> findByFirstname(String firstname);
@ScanConsistency(query = QueryScanConsistency.REQUEST_PLUS)
UserCol getById(String id);
List<UserCol> findByFirstnameIn(String... firstnames);
List<UserCol> findByFirstnameIn(JsonArray firstnames);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2017-2021 the original author or authors.
* Copyright 2017-2022 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.
@@ -91,6 +91,16 @@ public class CouchbaseRepositoryQueryCollectionIntegrationTests extends Collecti
super.afterEach();
}
@Test
void findByKey() {
UserCol userCol = new UserCol("101", "userColFirst", "userColLast");
userColRepository.save(userCol);
UserCol found = userColRepository.getById(userCol.getId());
System.err.println("found: " + found);
assertEquals(userCol, found);
userColRepository.delete(found);
}
@Test
public void myTest() {

View File

@@ -189,8 +189,8 @@ class N1qlQueryCreatorTests {
converter, bucketName);
Query query = creator.createQuery();
assertEquals(query.export(),
" WHERE " + where(x("META(`" + bucketName + "`).`id`")).isNotNull().and(i("firstname")).is("Oliver").export());
assertEquals(" WHERE " + where(x("META().`id`")).isNotNull().and(i("firstname")).is("Oliver").export(),
query.export());
}
@Test // https://github.com/spring-projects/spring-data-couchbase/issues/1072
@@ -204,8 +204,9 @@ class N1qlQueryCreatorTests {
getAccessor(getParameters(method), 1611287177404088320L, "Oliver"), queryMethod, converter, bucketName);
Query query = creator.createQuery();
assertEquals(query.export(), " WHERE " + where(x("META(`" + bucketName + "`).`cas`")).is(1611287177404088320L)
.and(i("firstname")).is("Oliver").export());
assertEquals(
" WHERE " + where(x("META().`cas`")).is(1611287177404088320L).and(i("firstname")).is("Oliver").export(),
query.export());
}
private ParameterAccessor getAccessor(Parameters<?, ?> params, Object... values) {