From 513c16a7c2fc5e4ab6fba7f2839c431201b4733a Mon Sep 17 00:00:00 2001 From: Subhashni Balakrishnan Date: Tue, 25 Sep 2018 14:05:33 -0700 Subject: [PATCH] DATACOUCH-407 - Use meta prefix for metadata properties in N1ql predicates Change part tree based N1ql query construction for metadata properties to add meta prefix. The metadata information stored as properties are version and id. The meta prefix is currently empty without the bucket name, referring the bucket could be an enhancement in future, but it should not break things as there is only one bucket involved in a repository part tree query. --- .../repository/N1qlCouchbaseRepositoryTests.java | 6 ++++++ .../data/couchbase/repository/PartyRepository.java | 2 ++ .../ReactiveN1qlCouchbaseRepositoryTests.java | 8 ++++++++ .../repository/ReactivePartyRepository.java | 1 + .../mapping/BasicCouchbasePersistentProperty.java | 6 ++++++ .../repository/query/support/N1qlUtils.java | 12 ++++++------ 6 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/integration/java/org/springframework/data/couchbase/repository/N1qlCouchbaseRepositoryTests.java b/src/integration/java/org/springframework/data/couchbase/repository/N1qlCouchbaseRepositoryTests.java index 988a21fbe..1133e31fe 100644 --- a/src/integration/java/org/springframework/data/couchbase/repository/N1qlCouchbaseRepositoryTests.java +++ b/src/integration/java/org/springframework/data/couchbase/repository/N1qlCouchbaseRepositoryTests.java @@ -195,4 +195,10 @@ public void testDeleteQuery() { assertTrue(partyList.size() == 1); } + @Test + public void testN1qlMetaPropertyConstructionInPartTree() { + partyRepository.save(new Party("testN1qlMetaPropertyConstructionInPartTree", "", "", null, 0, null)); + List parties = partyRepository.findByKeyLike("%Meta%"); + assertTrue("Party ids contain substring party", parties.size() >= 1); + } } diff --git a/src/integration/java/org/springframework/data/couchbase/repository/PartyRepository.java b/src/integration/java/org/springframework/data/couchbase/repository/PartyRepository.java index 8c0d9beb1..4993c4407 100644 --- a/src/integration/java/org/springframework/data/couchbase/repository/PartyRepository.java +++ b/src/integration/java/org/springframework/data/couchbase/repository/PartyRepository.java @@ -89,4 +89,6 @@ public interface PartyRepository extends CouchbaseRepository { List findByDescriptionOrName(String description, String name); List removeByDescriptionOrName(String description, String name); + + List findByKeyLike(String key); } diff --git a/src/integration/java/org/springframework/data/couchbase/repository/ReactiveN1qlCouchbaseRepositoryTests.java b/src/integration/java/org/springframework/data/couchbase/repository/ReactiveN1qlCouchbaseRepositoryTests.java index 05459472c..3ad9d7758 100644 --- a/src/integration/java/org/springframework/data/couchbase/repository/ReactiveN1qlCouchbaseRepositoryTests.java +++ b/src/integration/java/org/springframework/data/couchbase/repository/ReactiveN1qlCouchbaseRepositoryTests.java @@ -18,6 +18,7 @@ import static org.junit.Assert.*; +import java.util.List; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -123,4 +124,11 @@ public void testPartTreeQuery() { long count = partyRepository.countAllByDescriptionNotNull().block(); assertEquals("Test N1QL part tree based query", 15, count); } + + @Test + public void testN1qlMetaPropertyConstructionInPartTree() { + partyRepository.save(new Party("reactiveTestN1qlMetaPropertyConstructionInPartTree", "", "", null, 0, null)).block(); + List parties = partyRepository.findByKeyLike("%Meta%").collectList().block(); + assertTrue("Party ids contain substring party", parties.size() >= 1); + } } diff --git a/src/integration/java/org/springframework/data/couchbase/repository/ReactivePartyRepository.java b/src/integration/java/org/springframework/data/couchbase/repository/ReactivePartyRepository.java index 4a5605067..bd3d04c6a 100644 --- a/src/integration/java/org/springframework/data/couchbase/repository/ReactivePartyRepository.java +++ b/src/integration/java/org/springframework/data/couchbase/repository/ReactivePartyRepository.java @@ -57,4 +57,5 @@ public interface ReactivePartyRepository extends ReactiveCouchbaseRepository findByDescriptionOrName(String description, String name); + Flux findByKeyLike(String key); } diff --git a/src/main/java/org/springframework/data/couchbase/core/mapping/BasicCouchbasePersistentProperty.java b/src/main/java/org/springframework/data/couchbase/core/mapping/BasicCouchbasePersistentProperty.java index 6e756fdc9..8eba953a7 100644 --- a/src/main/java/org/springframework/data/couchbase/core/mapping/BasicCouchbasePersistentProperty.java +++ b/src/main/java/org/springframework/data/couchbase/core/mapping/BasicCouchbasePersistentProperty.java @@ -43,6 +43,8 @@ public class BasicCouchbasePersistentProperty implements CouchbasePersistentProperty { private final FieldNamingStrategy fieldNamingStrategy; + private final String ID_FIELD_NAME = "id"; + private final String VERSION_FIELD_NAME = "cas"; /** * Create a new instance of the BasicCouchbasePersistentProperty class. @@ -75,6 +77,10 @@ protected Association createAssociation() { */ @Override public String getFieldName() { + + if (isIdProperty() && getOwner().getIdProperty().equals(this)) return ID_FIELD_NAME; + if (isVersionProperty()) return VERSION_FIELD_NAME; + com.couchbase.client.java.repository.annotation.Field annotation = getField(). getAnnotation(com.couchbase.client.java.repository.annotation.Field.class); diff --git a/src/main/java/org/springframework/data/couchbase/repository/query/support/N1qlUtils.java b/src/main/java/org/springframework/data/couchbase/repository/query/support/N1qlUtils.java index 78e733e32..b469e82d2 100644 --- a/src/main/java/org/springframework/data/couchbase/repository/query/support/N1qlUtils.java +++ b/src/main/java/org/springframework/data/couchbase/repository/query/support/N1qlUtils.java @@ -24,7 +24,10 @@ import static org.springframework.data.couchbase.core.support.TemplateUtils.*; import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; import java.util.List; +import java.util.Set; import org.springframework.core.convert.converter.Converter; import org.springframework.data.couchbase.core.convert.CouchbaseConverter; @@ -60,18 +63,15 @@ * @author Mark Paluch */ public class N1qlUtils { + //As per https://docs.couchbase.com/server/5.5/n1ql/n1ql-language-reference/indexing-meta-info.html + final static Set META_PROPERTIES = new HashSet<>(Arrays.asList("id", "expiration", "cas")); /** * A converter that can be used to extract the {@link CouchbasePersistentProperty#getFieldName() fieldName}, * eg. when one wants a path from {@link PersistentPropertyPath#toDotPath(Converter)} made of escaped field names. */ public static final Converter FIELD_NAME_ESCAPED = - new Converter() { - @Override - public String convert(CouchbasePersistentProperty source) { - return "`" + source.getFieldName() + "`"; - } - }; + (source) -> META_PROPERTIES.contains(source.getFieldName()) ? "META()." + source.getFieldName() : "`" + source.getFieldName() + "`"; /** * Escape the given bucketName and produce an {@link Expression}.