Skip to content

Commit

Permalink
Improving SortOrder API
Browse files Browse the repository at this point in the history
- Implementing props constructor to init an ASC SortOrder by default
- Adding another direction and props constructor for extra flexibility
- Creating new methods to facilitate addition of new sort order rules
- Implementing unit tests
- Writing documentation

Original pull request: #483

(cherry picked from commit 98c40fe)
  • Loading branch information
jdorleans authored and meistermeier committed May 14, 2018
1 parent 2d6afc8 commit e5b6a2f
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 33 deletions.
73 changes: 66 additions & 7 deletions core/src/main/java/org/neo4j/ogm/cypher/query/SortOrder.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,28 +15,89 @@
import java.util.ArrayList;
import java.util.List;

import static org.neo4j.ogm.cypher.query.SortOrder.Direction.ASC;
import static org.neo4j.ogm.cypher.query.SortOrder.Direction.DESC;

/**
* @author Vince Bickers
*/
public class SortOrder {

public enum Direction {

ASC, DESC
}

private List<SortClause> sortClauses = new ArrayList<>();
private List<SortClause> sortClauses;

/**
* Creates SortOrder with a empty list of {@link SortClause}.
*/
public SortOrder() {
sortClauses = new ArrayList<>();
}

/**
* Creates SortOrder with a new {@link SortClause} containing properties ordered by {@link Direction#ASC}.
*
* @param properties list of properties ordered by {@link Direction#ASC}
*/
public SortOrder(String... properties) {
this(ASC, properties);
}

/**
* Creates SortOrder with a new {@link SortClause} containing properties ordered by direction.
*
* @param direction the specified {@link Direction} can be either ASC or DESC
* @param properties list of properties ordered by direction
*/
public SortOrder(Direction direction, String... properties) {
this();
add(direction, properties);
}


/**
* Adds a new {@link SortClause} containing properties ordered by {@link Direction#ASC}.
*
* @param properties list of properties ordered by {@link Direction#ASC}
*/
public SortOrder add(String... properties) {
return add(ASC, properties);
}

/**
* Adds a new {@link SortClause} containing properties ordered by direction.
*
* @param direction the specified {@link Direction} can be either ASC or DESC
* @param properties list of properties ordered by direction
*/
public SortOrder add(Direction direction, String... properties) {
sortClauses.add(new SortClause(direction, properties));
return this;
}

public SortOrder add(String... properties) {
sortClauses.add(new SortClause(Direction.ASC, properties));
return this;
/**
* Adds a new {@link SortClause} containing properties ordered by {@link Direction#ASC}.
*
* @param properties list of properties ordered by {@link Direction#ASC}
*/
public SortOrder asc(String... properties) {
return add(ASC, properties);
}

/**
* Adds a new {@link SortClause} containing properties ordered by {@link Direction#DESC}.
*
* @param properties list of properties ordered by {@link Direction#DESC}
*/
public SortOrder desc(String... properties) {
return add(DESC, properties);
}

/**
* Return the list of existing {@link SortClause}.
*/
public List<SortClause> sortClauses() {
return sortClauses;
}
Expand All @@ -58,5 +119,3 @@ public String toString() {
return sb.toString();
}
}


Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,17 @@
*/
package org.neo4j.ogm.session.request.strategy;

import static org.assertj.core.api.Assertions.*;

import org.junit.Before;
import org.junit.Test;
import org.neo4j.ogm.cypher.ComparisonOperator;
import org.neo4j.ogm.cypher.Filter;
import org.neo4j.ogm.cypher.Filters;
import org.neo4j.ogm.cypher.query.SortOrder;
import org.neo4j.ogm.session.request.strategy.impl.RelationshipQueryStatements;

import static org.assertj.core.api.Assertions.assertThat;
import static org.neo4j.ogm.cypher.ComparisonOperator.EQUALS;
import static org.neo4j.ogm.cypher.query.SortOrder.Direction.DESC;

/**
* @author Vince Bickers
*/
Expand All @@ -38,7 +39,7 @@ public void setUp() {
}

@Test
public void testFindByLabel() throws Exception {
public void testFindByLabel() {
sortOrder.add("distance");
String statement = query.findByType("ORBITS", 3).setSortOrder(sortOrder).getStatement();
String expected = "MATCH ()-[r0:`ORBITS`]-() WITH DISTINCT(r0) as r0,startnode(r0) AS n, endnode(r0) AS m " +
Expand All @@ -48,8 +49,8 @@ public void testFindByLabel() throws Exception {
}

@Test
public void testFindByProperty() throws Exception {
filters.add(new Filter("distance", ComparisonOperator.EQUALS, 60.2));
public void testFindByProperty() {
filters.add(new Filter("distance", EQUALS, 60.2));
sortOrder.add("aphelion");
String expected = "MATCH (n)-[r0:`ORBITS`]->(m) WHERE r0.`distance` = { `distance_0` } " +
"WITH DISTINCT(r0) as r0,startnode(r0) AS n, endnode(r0) AS m ORDER BY r0.aphelion " +
Expand All @@ -61,19 +62,31 @@ public void testFindByProperty() throws Exception {

@Test
public void testMultipleSortOrders() {
sortOrder.add(SortOrder.Direction.DESC, "distance", "aphelion");
String statement = query.findByType("ORBITS", 3).setSortOrder(sortOrder).getStatement();
String expected = "MATCH ()-[r0:`ORBITS`]-() WITH DISTINCT(r0) as r0,startnode(r0) AS n, " +
String cypher = "MATCH ()-[r0:`ORBITS`]-() WITH DISTINCT(r0) as r0,startnode(r0) AS n, " +
"endnode(r0) AS m ORDER BY r0.distance DESC,r0.aphelion DESC " +
"MATCH p1 = (n)-[*0..3]-() WITH r0, COLLECT(DISTINCT p1) AS startPaths, m " +
"MATCH p2 = (m)-[*0..3]-() WITH r0, startPaths, COLLECT(DISTINCT p2) AS endPaths " +
"WITH r0,startPaths + endPaths AS paths UNWIND paths AS p RETURN DISTINCT p, ID(r0)";
assertThat(statement).isEqualTo(expected);
check(cypher, query.findByType("ORBITS", 3).setSortOrder(sortOrder.add(DESC, "distance", "aphelion")).getStatement());
check(cypher, query.findByType("ORBITS", 3).setSortOrder(new SortOrder(DESC, "distance", "aphelion")).getStatement());
check(cypher, query.findByType("ORBITS", 3).setSortOrder(new SortOrder().desc("distance", "aphelion")).getStatement());
}

@Test
public void testDefaultMultipleSortOrders() {
String cypher = "MATCH ()-[r0:`ORBITS`]-() WITH DISTINCT(r0) as r0,startnode(r0) AS n, " +
"endnode(r0) AS m ORDER BY r0.distance,r0.aphelion " +
"MATCH p1 = (n)-[*0..3]-() WITH r0, COLLECT(DISTINCT p1) AS startPaths, m " +
"MATCH p2 = (m)-[*0..3]-() WITH r0, startPaths, COLLECT(DISTINCT p2) AS endPaths " +
"WITH r0,startPaths + endPaths AS paths UNWIND paths AS p RETURN DISTINCT p, ID(r0)";
check(cypher, query.findByType("ORBITS", 3).setSortOrder(sortOrder.add("distance", "aphelion")).getStatement());
check(cypher, query.findByType("ORBITS", 3).setSortOrder(new SortOrder("distance", "aphelion")).getStatement());
check(cypher, query.findByType("ORBITS", 3).setSortOrder(new SortOrder().asc("distance", "aphelion")).getStatement());
}

@Test
public void testDifferentSortDirections() {
sortOrder.add(SortOrder.Direction.DESC, "type").add("name");
sortOrder.add(DESC, "type").add("name");
String statement = query.findByType("ORBITS", 3).setSortOrder(sortOrder).getStatement();
String expected = "MATCH ()-[r0:`ORBITS`]-() WITH DISTINCT(r0) as r0,startnode(r0) AS n, endnode(r0) AS m " +
"ORDER BY r0.type DESC,r0.name MATCH p1 = (n)-[*0..3]-() WITH r0, COLLECT(DISTINCT p1) AS startPaths, m " +
Expand All @@ -82,4 +95,8 @@ public void testDifferentSortDirections() {
"UNWIND paths AS p RETURN DISTINCT p, ID(r0)";
assertThat(statement).isEqualTo(expected);
}

private void check(String expected, String actual) {
assertThat(actual).isEqualTo(expected);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,16 @@
*/
package org.neo4j.ogm.session.request.strategy.impl;

import static org.assertj.core.api.Assertions.*;

import org.junit.Before;
import org.junit.Test;
import org.neo4j.ogm.cypher.ComparisonOperator;
import org.neo4j.ogm.cypher.Filter;
import org.neo4j.ogm.cypher.Filters;
import org.neo4j.ogm.cypher.query.SortOrder;

import static org.assertj.core.api.Assertions.assertThat;
import static org.neo4j.ogm.cypher.ComparisonOperator.EQUALS;
import static org.neo4j.ogm.cypher.query.SortOrder.Direction.DESC;

/**
* @author Vince Bickers
*/
Expand All @@ -46,54 +47,63 @@ public void testFindByType() {

@Test
public void testFindByProperty() {
sortOrder.add(SortOrder.Direction.DESC, "weight");
filters.add(new Filter("name", ComparisonOperator.EQUALS, "velociraptor"));
sortOrder.add(DESC, "weight");
filters.add(new Filter("name", EQUALS, "velociraptor"));
check(
"MATCH (n:`Raptor`) WHERE n.`name` = { `name_0` } WITH n ORDER BY n.weight DESC MATCH p=(n)-[*0..2]-(m) RETURN p, ID(n)",
query.findByType("Raptor", filters, 2).setSortOrder(sortOrder).getStatement());
}

@Test
public void testFindByTypeDepthZero() {
sortOrder.add(SortOrder.Direction.DESC, "name");
sortOrder.add(DESC, "name");
check("MATCH (n:`Raptor`) WITH n ORDER BY n.name DESC RETURN n",
query.findByType("Raptor", 0).setSortOrder(sortOrder).getStatement());
}

@Test
public void testByPropertyDepthZero() {
filters.add(new Filter("name", ComparisonOperator.EQUALS, "velociraptor"));
sortOrder.add(SortOrder.Direction.DESC, "weight");
filters.add(new Filter("name", EQUALS, "velociraptor"));
sortOrder.add(DESC, "weight");
check("MATCH (n:`Raptor`) WHERE n.`name` = { `name_0` } WITH n ORDER BY n.weight DESC RETURN n",
query.findByType("Raptor", filters, 0).setSortOrder(sortOrder).getStatement());
}

@Test
public void testFindByTypeDepthInfinite() {
sortOrder.add(SortOrder.Direction.DESC, "name");
sortOrder.add(DESC, "name");
check("MATCH (n:`Raptor`) WITH n ORDER BY n.name DESC MATCH p=(n)-[*0..]-(m) RETURN p, ID(n)",
query.findByType("Raptor", -1).setSortOrder(sortOrder).getStatement());
}

@Test
public void testFindByPropertyDepthInfinite() {
sortOrder.add(SortOrder.Direction.DESC, "name");
filters.add(new Filter("name", ComparisonOperator.EQUALS, "velociraptor"));
sortOrder.add(DESC, "name");
filters.add(new Filter("name", EQUALS, "velociraptor"));
check(
"MATCH (n:`Raptor`) WHERE n.`name` = { `name_0` } WITH n ORDER BY n.name DESC MATCH p=(n)-[*0..]-(m) RETURN p, ID(n)",
query.findByType("Raptor", filters, -1).setSortOrder(sortOrder).getStatement());
}

@Test
public void testMultipleSortOrders() {
sortOrder.add(SortOrder.Direction.DESC, "age", "name");
check("MATCH (n:`Raptor`) WITH n ORDER BY n.age DESC,n.name DESC RETURN n",
query.findByType("Raptor", 0).setSortOrder(sortOrder).getStatement());
String cypher = "MATCH (n:`Raptor`) WITH n ORDER BY n.age DESC,n.name DESC RETURN n";
check(cypher, query.findByType("Raptor", 0).setSortOrder(sortOrder.add(DESC, "age", "name")).getStatement());
check(cypher, query.findByType("Raptor", 0).setSortOrder(new SortOrder(DESC, "age", "name")).getStatement());
check(cypher, query.findByType("Raptor", 0).setSortOrder(new SortOrder().desc("age", "name")).getStatement());
}

@Test
public void testDefaultMultipleSortOrders() {
String cypher = "MATCH (n:`Raptor`) WITH n ORDER BY n.age,n.name RETURN n";
check(cypher, query.findByType("Raptor", 0).setSortOrder(sortOrder.add("age", "name")).getStatement());
check(cypher, query.findByType("Raptor", 0).setSortOrder(new SortOrder("age", "name")).getStatement());
check(cypher, query.findByType("Raptor", 0).setSortOrder(new SortOrder().asc("age", "name")).getStatement());
}

@Test
public void testDifferentSortDirections() {
sortOrder.add(SortOrder.Direction.DESC, "age").add("name");
sortOrder.add(DESC, "age").add("name");
check("MATCH (n:`Raptor`) WITH n ORDER BY n.age DESC,n.name RETURN n",
query.findByType("Raptor", 0).setSortOrder(sortOrder).getStatement());
}
Expand Down

0 comments on commit e5b6a2f

Please sign in to comment.