DATACOUCH-187 - Allow counting queries and single projections.
This change allows simple projections to types long, boolean, String when an inline N1QL query uses an aggregation function like AVG, COUNT. The projection's result must be a single row with a single key/value pair in the N1QL response. Only the value gets returned.
This commit is contained in:
@@ -16,22 +16,21 @@
|
||||
|
||||
package org.springframework.data.couchbase.repository;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import com.couchbase.client.java.Bucket;
|
||||
import com.couchbase.client.java.error.DocumentDoesNotExistException;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DataRetrievalFailureException;
|
||||
import org.springframework.data.couchbase.IntegrationTestApplicationConfig;
|
||||
import org.springframework.data.couchbase.core.CouchbaseQueryExecutionException;
|
||||
import org.springframework.data.couchbase.repository.config.RepositoryOperationsMapping;
|
||||
import org.springframework.data.couchbase.repository.support.CouchbaseRepositoryFactory;
|
||||
import org.springframework.data.couchbase.repository.support.IndexManager;
|
||||
@@ -76,9 +75,9 @@ public class N1qlCrudRepositoryTests {
|
||||
|
||||
@After
|
||||
public void cleanUp() {
|
||||
try { itemRepository.delete(KEY_ITEM); } catch (DocumentDoesNotExistException e) {}
|
||||
try { partyRepository.delete(KEY_PARTY); } catch (DocumentDoesNotExistException e) {}
|
||||
try { partyRepository.delete(KEY_PARTY_KEYWORD); } catch (DocumentDoesNotExistException e) {}
|
||||
try { itemRepository.delete(KEY_ITEM); } catch (DataRetrievalFailureException e) {}
|
||||
try { partyRepository.delete(KEY_PARTY); } catch (DataRetrievalFailureException e) {}
|
||||
try { partyRepository.delete(KEY_PARTY_KEYWORD); } catch (DataRetrievalFailureException e) {}
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -107,4 +106,56 @@ public class N1qlCrudRepositoryTests {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldGenerateCountProjection() {
|
||||
Party partyHasKeyword = new Party(KEY_PARTY_KEYWORD, "party", null, new Date(), 40, new Point(500, 500));
|
||||
partyRepository.save(partyHasKeyword);
|
||||
long countTotal = partyRepository.count();
|
||||
long countCustom = partyRepository.countAllByDescriptionNotNull();
|
||||
assertEquals(countTotal - 1, countCustom);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldCountWhenReturningLongAndUsingStringSelectFromSpEL() {
|
||||
Party partyHasKeyword = new Party(KEY_PARTY_KEYWORD, "party", "second party", new Date(), 40, new Point(500, 500));
|
||||
partyRepository.save(partyHasKeyword);
|
||||
|
||||
long countTotal = partyRepository.count();
|
||||
long countCustom = partyRepository.countCustom();
|
||||
assertEquals(countTotal, countCustom);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldCustomCountWhenReturningLongAndUsingStringWithoutSpEL() {
|
||||
Party partyHasKeyword = new Party(KEY_PARTY_KEYWORD, "party", "second party", new Date(), 40, new Point(500, 500));
|
||||
partyRepository.save(partyHasKeyword);
|
||||
|
||||
long countTotal = partyRepository.count();
|
||||
long countCustom = partyRepository.countCustomPlusFive();
|
||||
assertEquals(countTotal + 5, countCustom);
|
||||
}
|
||||
|
||||
@Test(expected = CouchbaseQueryExecutionException.class)
|
||||
public void shouldFailConversionWithStringReturnType() {
|
||||
Party partyHasKeyword = new Party(KEY_PARTY_KEYWORD, "party", "desc is a N1QL keyword", new Date(), 40, new Point(500, 500));
|
||||
partyRepository.save(partyHasKeyword);
|
||||
|
||||
String someString = partyRepository.findSomeString();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldDoNumericProjectionWithStringBasedQuery() {
|
||||
Party partyHasKeyword = new Party(KEY_PARTY_KEYWORD, "party", "desc is a N1QL keyword", new Date(), 4000000, new Point(500, 500));
|
||||
partyRepository.save(partyHasKeyword);
|
||||
|
||||
long max = partyRepository.findMaxAttendees();
|
||||
assertEquals(4000000, max);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldDoBooleanProjectionWithStringBasedQuery() {
|
||||
boolean someBoolean = partyRepository.justABoolean();
|
||||
assertEquals(true, someBoolean);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,14 @@ package org.springframework.data.couchbase.repository;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.couchbase.core.query.Query;
|
||||
import org.springframework.data.couchbase.core.query.View;
|
||||
import org.springframework.data.couchbase.core.query.ViewIndexed;
|
||||
|
||||
/**
|
||||
* @author Simon Baslé
|
||||
*/
|
||||
@ViewIndexed(designDoc = "party", viewName = "all")
|
||||
public interface PartyRepository extends CouchbaseRepository<Party, String> {
|
||||
|
||||
List<Party> findByAttendeesGreaterThanEqual(int minAttendees);
|
||||
@@ -19,4 +22,20 @@ public interface PartyRepository extends CouchbaseRepository<Party, String> {
|
||||
|
||||
List<Object> findAllByDescriptionNotNull();
|
||||
|
||||
long countAllByDescriptionNotNull();
|
||||
|
||||
@Query("SELECT MAX(attendees) FROM #{#n1ql.bucket} WHERE #{#n1ql.filter}")
|
||||
long findMaxAttendees();
|
||||
|
||||
@Query("SELECT `desc` FROM #{#n1ql.bucket} WHERE #{#n1ql.filter}")
|
||||
String findSomeString();
|
||||
|
||||
@Query("SELECT count(*) + 5 FROM #{#n1ql.bucket} WHERE #{#n1ql.filter}")
|
||||
long countCustomPlusFive();
|
||||
|
||||
@Query("#{#n1ql.selectEntity} WHERE #{#n1ql.filter}")
|
||||
long countCustom();
|
||||
|
||||
@Query("SELECT 1 = 1")
|
||||
boolean justABoolean();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user