Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
DATAGRAPH-813 - Full implementation and associated tests.
  • Loading branch information
Vince Bickers committed Oct 21, 2016
1 parent 73f9834 commit da42541
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 45 deletions.
Expand Up @@ -13,20 +13,19 @@

package org.springframework.data.neo4j.repository.query.derived;

import java.util.*;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.neo4j.ogm.cypher.Filter;
import org.neo4j.ogm.cypher.Filters;
import org.neo4j.ogm.cypher.function.DistanceComparison;
import org.neo4j.ogm.cypher.function.DistanceFromPoint;
import org.neo4j.ogm.cypher.function.FilterFunction;
import org.neo4j.ogm.cypher.query.AbstractRequest;
import org.neo4j.ogm.cypher.query.Pagination;
import org.neo4j.ogm.cypher.query.SortOrder;
import org.neo4j.ogm.model.Result;
import org.neo4j.ogm.session.Neo4jSession;
import org.neo4j.ogm.session.Session;
import org.neo4j.ogm.session.request.strategy.VariableDepthQuery;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.SliceImpl;
Expand Down Expand Up @@ -58,7 +57,7 @@ public class DerivedGraphRepositoryQuery implements RepositoryQuery {
private final PartTree tree;

protected final Session session;
protected final EntityMetadata<?> info;
protected final EntityMetadata info;

private final int DEFAULT_QUERY_DEPTH = 1;

Expand Down Expand Up @@ -91,21 +90,11 @@ class CountByQuery implements RepositoryQuery {
@Override
public Object execute(Object[] parameters) {

Class<?> domainClass = info.getJavaType();

if (getQueryMethod().getReturnedObjectType().equals(Long.class)) {
String label = ((Neo4jSession) session).metaData().classInfo(domainClass.getName()).neo4jName();
Filters filters = resolveParams(parameters);

// TODO? create a specific implementation, e.g. CountQuery().findByProperties(label, filters)
AbstractRequest query = new VariableDepthQuery().findByProperties(label, filters, 0);

String statement = query.getStatement().replace("RETURN n", "RETURN COUNT(n)");
Result result = session.query(statement, query.getParameters());
Map<String, Object> resultMap = result.iterator().next();
return Long.parseLong(resultMap.get("COUNT(n)").toString());
return session.count(info.getJavaType(), filters);
} else {
throw new RuntimeException("Count queries must return a Long");
throw new RuntimeException("Long is required as the return type of a Count query");
}
}

Expand All @@ -120,35 +109,18 @@ class DeleteByQuery implements RepositoryQuery {
@Override
public Object execute(Object[] parameters) {

Class<?> domainClass = info.getJavaType();
String label = ((Neo4jSession) session).metaData().classInfo(domainClass.getName()).neo4jName();
Filters filters = resolveParams(parameters);

// TODO? create a specific implementation, e.g. DeleteQuery().findByProperties(label, filters)
AbstractRequest query = new VariableDepthQuery().findByProperties(label, filters, 0);

Class<?> returnType = graphQueryMethod.resolveConcreteReturnType();
String statement = query.getStatement();

if (returnType.equals(Long.class)) {

if (graphQueryMethod.isCollectionQuery()) {
statement = statement.replace("RETURN n", "OPTIONAL MATCH (n)-[r]-() DELETE r, n RETURN id(n)");
Result result = session.query(statement, query.getParameters());
List<Long> deletedIds = new ArrayList();
for (Map<String, Object> resultEntry : result) {
deletedIds.add(Long.parseLong(resultEntry.get("id(n)").toString()));
}
return deletedIds;
return session.delete(info.getJavaType(), filters, true); // list deleted ids
} else {
return session.delete(info.getJavaType(), filters, false); // count deleted ids
}

statement = statement.replace("RETURN n", "OPTIONAL MATCH (n)-[r]-() DELETE r, n RETURN COUNT(n)");
Result result = session.query(statement, query.getParameters());
Map<String, Object> resultMap = result.iterator().next();
return Long.parseLong(resultMap.get("COUNT(n)").toString());
}

throw new RuntimeException("Return type of Delete query must Long or Iterable<Long>");
throw new RuntimeException("Long or Iterable<Long> is required as the return type of a Delete query");
}

@Override
Expand Down Expand Up @@ -391,4 +363,5 @@ int configuration() {
return NO_PAGING_OR_SORTING;
}
}

}
Expand Up @@ -13,11 +13,11 @@

package org.springframework.data.neo4j.examples.movies.repo;

import java.util.List;

import org.springframework.data.neo4j.examples.movies.domain.Rating;
import org.springframework.data.neo4j.repository.GraphRepository;

import java.util.List;

/**
* @author Luanne Misquitta
*/
Expand Down Expand Up @@ -49,4 +49,10 @@ public interface RatingRepository extends GraphRepository<Rating> {

List<Rating> findByUserNameAndUserMiddleName(String username, String middleName);

Long countByStars(int stars);

Long removeByUserName(String username);

List<Long> deleteByStarsOrRatingTimestampGreaterThan(int stars, long ratingTimestamp);

}
Expand Up @@ -393,4 +393,98 @@ public void doInTransactionWithoutResult(TransactionStatus status) {
}
});
}

/**
* @see DATAGRAPH-813
*/
@Test
@Transactional
public void shouldDeleteAndReturnDeletedIds() {
User critic = new User("Gary");
TempMovie film = new TempMovie("Fast and Furious XVII");
Rating filmRating = critic.rate(film, 2, "They've made far too many of these films now!");
filmRating.setRatingTimestamp(1000);

userRepository.save(critic);

List<Long> ratingIds = ratingRepository.deleteByStarsOrRatingTimestampGreaterThan(2, 500);
assertEquals(filmRating.getId(), ratingIds.get(0));
assertEquals(1, ratingIds.size());

List<Rating> ratings = ratingRepository.findByStarsAndRatingTimestamp(2, 2000);
assertEquals(0, ratings.size());
}

/**
* @see DATAGRAPH-813
*/
@Test
@Transactional
public void shouldCountByStars() {
User critic = new User("Gary");
TempMovie film = new TempMovie("Fast and Furious XVII");
Rating filmRating = critic.rate(film, 2, "They've made far too many of these films now!");
filmRating.setRatingTimestamp(1000);

userRepository.save(critic);

long starredRatings = ratingRepository.countByStars(2);
assertEquals(1L, starredRatings);

}

/**
* @see DATAGRAPH-813
*/
@Test
@Transactional
public void shouldRemoveByUserNameAndReturnCountOfDeletedObjects() {
User critic = new User("Gary");
TempMovie film = new TempMovie("Fast and Furious XVII");
Rating filmRating = critic.rate(film, 2, "They've made far too many of these films now!");
filmRating.setRatingTimestamp(1000);

userRepository.save(critic);

long countRemovedObjects = ratingRepository.removeByUserName("Gary");
assertEquals(1L, countRemovedObjects);

}

/**
* @see DATAGRAPH-813
*/
@Test
@Transactional
public void shouldCountNothingWithNonMatchingFilter() {
User critic = new User("Gary");
TempMovie film = new TempMovie("Fast and Furious XVII");
Rating filmRating = critic.rate(film, 2, "They've made far too many of these films now!");
filmRating.setRatingTimestamp(1000);

userRepository.save(critic);

long countRemovedObjects = ratingRepository.removeByUserName("Bill");
assertEquals(0L, countRemovedObjects);

}

/**
* @see DATAGRAPH-813
*/
@Test
@Transactional
public void shouldDeleteNothingWithNonMatchingFilter() {
User critic = new User("Gary");
TempMovie film = new TempMovie("Fast and Furious XVII");
Rating filmRating = critic.rate(film, 2, "They've made far too many of these films now!");
filmRating.setRatingTimestamp(1000);

userRepository.save(critic);

List<Long> deletedIds = ratingRepository.deleteByStarsOrRatingTimestampGreaterThan(3, 2000);
assertEquals(0L, deletedIds.size());

}

}
Expand Up @@ -159,10 +159,6 @@ public void shouldDeleteUserByNameAndReturnListOfDeletedUserIds() {

Assert.assertEquals(0, userRepository.count());

// TODO ??
// ensure that the ID field of deleted user objects is set to null;


}

@Test
Expand Down

0 comments on commit da42541

Please sign in to comment.