Commit 0667b85c authored by Chris Gioran's avatar Chris Gioran
Browse files

Added a sort GET parameter for index queries to determine the way results are ordered

Conflicts:

	server/src/main/java/org/neo4j/server/rest/web/DatabaseActions.java
parent 242e8ca0
Showing with 126 additions and 26 deletions
+126 -26
......@@ -24,6 +24,8 @@ import java.net.URI;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.ws.rs.core.HttpHeaders;
......@@ -201,8 +203,9 @@ public class IndexNodeFunctionalTest extends AbstractRestFunctionalTestBase
functionalTestHelper.nodeUri( nodeId ) ) ) )
.post( functionalTestHelper.indexNodeUri( indexName ) );
// look if we get one entry back
JaxRsResponse response = RestRequest.req()
.get( functionalTestHelper.indexNodeUri( indexName, key, URIHelper.encode( value ) ) );
JaxRsResponse response = RestRequest.req().get(
functionalTestHelper.indexNodeUri( indexName, key,
URIHelper.encode( value ) ) );
String entity = response.getEntity( String.class );
Collection<?> hits = (Collection<?>) JsonHelper.jsonToSingleValue( entity );
assertEquals( 1, hits.size() );
......@@ -275,6 +278,53 @@ public class IndexNodeFunctionalTest extends AbstractRestFunctionalTestBase
assertEquals( 1, hits.size() );
}
@Test
public void shouldAddToIndexAndRetrieveItByQuerySorted()
throws PropertyValueException
{
String indexName = "bobTheIndex";
String key = "Name";
long node1 = helper.createNode();
long node2 = helper.createNode();
helper.addNodeToIndex( indexName, key, "Builder2", node1 );
helper.addNodeToIndex( indexName, "Gender", "Male", node1 );
helper.addNodeToIndex( indexName, key, "Builder", node2 );
helper.addNodeToIndex( indexName, "Gender", "Male", node2 );
String entity = gen.get().expectedStatus( 200 ).get(
functionalTestHelper.indexNodeUri( indexName )
+ "?query=Name:Build~0.1%20AND%20Gender:Male&order=relevance" ).entity();
Collection<?> hits = (Collection<?>) JsonHelper.jsonToSingleValue( entity );
assertEquals( 2, hits.size() );
Iterator it = hits.iterator();
assertTrue( ( (String) ( (LinkedHashMap) it.next() ).get( "self" ) ).endsWith( Long.toString( node2 ) ) );
assertTrue( ( (String) ( (LinkedHashMap) it.next() ).get( "self" ) ).endsWith( Long.toString( node1 ) ) );
entity = gen.get().expectedStatus( 200 ).get(
functionalTestHelper.indexNodeUri( indexName )
+ "?query=Name:Build~0.1%20AND%20Gender:Male&order=index" ).entity();
hits = (Collection<?>) JsonHelper.jsonToSingleValue( entity );
assertEquals( 2, hits.size() );
it = hits.iterator();
assertTrue( ( (String) ( (LinkedHashMap) it.next() ).get( "self" ) ).endsWith( Long.toString( node1 ) ) );
assertTrue( ( (String) ( (LinkedHashMap) it.next() ).get( "self" ) ).endsWith( Long.toString( node2 ) ) );
entity = gen.get().expectedStatus( 200 ).get(
functionalTestHelper.indexNodeUri( indexName )
+ "?query=Name:Build~0.1%20AND%20Gender:Male&order=score" ).entity();
hits = (Collection<?>) JsonHelper.jsonToSingleValue( entity );
assertEquals( 2, hits.size() );
it = hits.iterator();
assertTrue( ( (String) ( (LinkedHashMap) it.next() ).get( "self" ) ).endsWith( Long.toString( node2 ) ) );
assertTrue( ( (String) ( (LinkedHashMap) it.next() ).get( "self" ) ).endsWith( Long.toString( node1 ) ) );
}
/**
* POST ${org.neo4j.server.rest.web}/index/node/{indexName}/{key}/{value}
* "http://uri.for.node.to.index"
......
......@@ -27,6 +27,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.lucene.search.Sort;
import org.neo4j.graphalgo.CommonEvaluators;
import org.neo4j.graphalgo.CostEvaluator;
import org.neo4j.graphalgo.GraphAlgoFactory;
......@@ -53,6 +54,7 @@ import org.neo4j.graphdb.index.UniqueFactory;
import org.neo4j.graphdb.traversal.TraversalDescription;
import org.neo4j.helpers.Pair;
import org.neo4j.helpers.collection.IterableWrapper;
import org.neo4j.index.lucene.QueryContext;
import org.neo4j.kernel.AbstractGraphDatabase;
import org.neo4j.kernel.TransactionBuilder;
import org.neo4j.kernel.Traversal;
......@@ -87,6 +89,9 @@ import org.neo4j.server.rest.repr.WeightedPathRepresentation;
public class DatabaseActions
{
public static final String SCORE_ORDER = "score";
public static final String RELEVANCE_ORDER = "relevance";
public static final String INDEX_ORDER = "index";
private final Database database;
private final AbstractGraphDatabase graphDb;
private final LeaseManager leases;
......@@ -900,25 +905,28 @@ public class DatabaseActions
}
public ListRepresentation getIndexedNodesByQuery( String indexName,
String query )
String query, String sort )
{
return getIndexedNodesByQuery( indexName, null, query );
return getIndexedNodesByQuery( indexName, null, query, sort );
}
public ListRepresentation getIndexedNodesByQuery( String indexName,
String key, String query )
String key, String query, String sort )
{
if ( !graphDb.index().existsForNodes( indexName ) )
throw new NotFoundException();
Index<Node> index = graphDb.index().forNodes( indexName );
List<Representation> representations = new ArrayList<Representation>();
QueryContext queryCtx = new QueryContext( query );
queryCtx = setOrdering( queryCtx, sort );
Transaction tx = beginTx();
try
{
if ( query != null )
{
for ( Node node : index.query( key, query ) )
IndexHits<Node> result = index.query( key, queryCtx );
for ( Node node : result)
{
representations.add( new NodeRepresentation( node ) );
}
......@@ -1140,23 +1148,37 @@ public class DatabaseActions
}
public ListRepresentation getIndexedRelationshipsByQuery( String indexName,
String query )
String query, String sort )
{
return getIndexedRelationshipsByQuery( indexName, null, query );
return getIndexedRelationshipsByQuery( indexName, null, query, sort );
}
public ListRepresentation getIndexedRelationshipsByQuery( String indexName,
String key, String query )
String key, String query, String sort )
{
if ( !graphDb.index().existsForRelationships( indexName ) )
throw new NotFoundException();
List<Representation> representations = new ArrayList<Representation>();
Index<Relationship> index = graphDb.index().forRelationships( indexName );
QueryContext queryCtx = new QueryContext( query );
if ( "indexOrder".equalsIgnoreCase( sort ) )
{
queryCtx = queryCtx.sort( Sort.INDEXORDER );
}
else if ( "relevance".equalsIgnoreCase( sort ) )
{
queryCtx = queryCtx.sort( Sort.RELEVANCE );
}
else if ( "score".equalsIgnoreCase( sort ) )
{
queryCtx = queryCtx.sortByScore();
}
Transaction tx = beginTx();
try
{
for ( Relationship rel : index.query( key, query ) )
for ( Relationship rel : index.query( key, queryCtx ) )
{
representations.add( new RelationshipRepresentation( rel ) );
}
......@@ -1434,6 +1456,23 @@ public class DatabaseActions
}
}
private final QueryContext setOrdering( QueryContext queryCtx, String order )
{
if ( INDEX_ORDER.equalsIgnoreCase( order ) )
{
return queryCtx.sort( Sort.INDEXORDER );
}
else if ( RELEVANCE_ORDER.equalsIgnoreCase( order ) )
{
return queryCtx.sort( Sort.RELEVANCE );
}
else if ( SCORE_ORDER.equalsIgnoreCase( order ) )
{
return queryCtx.sortByScore();
}
return queryCtx;
}
private interface PathRepresentationCreator<T extends Path>
{
PathRepresentation<T> from( T path );
......
......@@ -657,11 +657,13 @@ public class RestfulGraphDatabase
@GET
@Path( PATH_NAMED_NODE_INDEX )
public Response getIndexedNodesByQuery( @PathParam( "indexName" ) String indexName,
@QueryParam( "query" ) String query )
@QueryParam( "query" ) String query,
@QueryParam( "order" ) String order )
{
try
{
return output.ok( actions.getIndexedNodesByQuery( indexName, query ) );
return output.ok( actions.getIndexedNodesByQuery( indexName, query,
order ) );
}
catch ( NotFoundException nfe )
{
......@@ -901,12 +903,16 @@ public class RestfulGraphDatabase
@GET
@Path( PATH_NODE_INDEX_QUERY_WITH_KEY )
public Response getIndexedNodesByQuery( @PathParam( "indexName" ) String indexName,
@PathParam( "key" ) String key, @QueryParam( "query" ) String query )
public Response getIndexedNodesByQuery(
@PathParam( "indexName" ) String indexName,
@PathParam( "key" ) String key,
@QueryParam( "query" ) String query,
@PathParam( "order" ) String order )
{
try
{
return output.ok( actions.getIndexedNodesByQuery( indexName, key, query ) );
return output.ok( actions.getIndexedNodesByQuery( indexName, key,
query, order ) );
}
catch ( NotFoundException nfe )
{
......@@ -976,11 +982,13 @@ public class RestfulGraphDatabase
@GET
@Path( PATH_NAMED_RELATIONSHIP_INDEX )
public Response getIndexedRelationshipsByQuery( @PathParam( "indexName" ) String indexName,
@QueryParam( "query" ) String query )
@QueryParam( "query" ) String query,
@QueryParam( "order" ) String order )
{
try
{
return output.ok( actions.getIndexedRelationshipsByQuery( indexName, query ) );
return output.ok( actions.getIndexedRelationshipsByQuery(
indexName, query, order ) );
}
catch ( NotFoundException nfe )
{
......@@ -995,11 +1003,14 @@ public class RestfulGraphDatabase
@GET
@Path( PATH_RELATIONSHIP_INDEX_QUERY_WITH_KEY )
public Response getIndexedRelationshipsByQuery( @PathParam( "indexName" ) String indexName,
@PathParam( "key" ) String key, @QueryParam( "query" ) String query )
@PathParam( "key" ) String key,
@QueryParam( "query" ) String query,
@QueryParam( "order" ) String order )
{
try
{
return output.ok( actions.getIndexedRelationshipsByQuery( indexName, key, query ) );
return output.ok( actions.getIndexedRelationshipsByQuery(
indexName, key, query, order ) );
}
catch ( NotFoundException nfe )
{
......
......@@ -1283,8 +1283,8 @@ public class RestfulGraphDatabaseTest
.next();
// query for the first letter with which the nodes were indexed.
Response response = service.getIndexedNodesByQuery( matrixers.nodeIndexName, indexedKeyValue.getKey() + ":"
+ indexedKeyValue.getValue()
.substring( 0, 1 ) + "*" );
+ indexedKeyValue.getValue().substring( 0, 1 ) + "*",
"" /*default ordering*/);
assertEquals( Status.OK.getStatusCode(), response.getStatus() );
Collection<?> items = (Collection<?>) JsonHelper.jsonToSingleValue( entityAsString( response ) );
int counter = 0;
......@@ -1319,8 +1319,7 @@ public class RestfulGraphDatabaseTest
.next();
// query for the first letter with which the nodes were indexed.
Response response = service.getIndexedNodesByQuery( matrixers.nodeIndexName, indexedKeyValue.getKey(),
indexedKeyValue.getValue()
.substring( 0, 1 ) + "*" );
indexedKeyValue.getValue().substring( 0, 1 ) + "*", "" /*default ordering*/);
assertEquals( Status.OK.getStatusCode(), response.getStatus() );
Collection<?> items = (Collection<?>) JsonHelper.jsonToSingleValue( entityAsString( response ) );
int counter = 0;
......@@ -1402,8 +1401,8 @@ public class RestfulGraphDatabaseTest
helper.addRelationshipToIndex( indexName, key, value, relationshipId1 );
helper.addRelationshipToIndex( indexName, key, value, relationshipId2 );
Response response = service.getIndexedRelationshipsByQuery( indexName, key + ":" + value.substring( 0, 1 )
+ "*" );
Response response = service.getIndexedRelationshipsByQuery( indexName,
key + ":" + value.substring( 0, 1 ) + "*", "" /*default ordering*/);
assertEquals( Status.OK.getStatusCode(), response.getStatus() );
Collection<?> items = (Collection<?>) JsonHelper.jsonToSingleValue( entityAsString( response ) );
int counter = 0;
......@@ -1442,7 +1441,8 @@ public class RestfulGraphDatabaseTest
helper.addRelationshipToIndex( indexName, key, value, relationshipId1 );
helper.addRelationshipToIndex( indexName, key, value, relationshipId2 );
Response response = service.getIndexedRelationshipsByQuery( indexName, key, value.substring( 0, 1 ) + "*" );
Response response = service.getIndexedRelationshipsByQuery( indexName,
key, value.substring( 0, 1 ) + "*", "" /*default ordering*/);
assertEquals( Status.OK.getStatusCode(), response.getStatus() );
Collection<?> items = (Collection<?>) JsonHelper.jsonToSingleValue( entityAsString( response ) );
int counter = 0;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment