Paul Jackson Paul Jackson - 1 year ago 70
Java Question

A way to query Neo4j by property sorted by highest or lowest values

In Neo4j if I want to find nodes with the highest or lowest property values I can use the Cypher keywords Order By and Limit. I'd like to accomplish the same using the embedded API. I know Lucene can support this but can't see how to do this with Neo's API.

public TopFieldDocs search(Query query, int n, Sort sort)

Answer Source

I looked into this and the answer is Yes, this can be done. The second argument in IndexHits<T> query( String key, Object queryOrQueryObject ) can be a parseable (by org.apache.lucene.queryParser.QueryParser) String, a, or a org.neo4j.index.lucene.QueryContext

Here's a code snippet that allows for requiring an "EntityType" property to have a specific value, requires a numeric property to be non-blank, and returns n hits sorted by the numeric property.

List<TopNValue> values = new ArrayList<>();
QueryContext queryContext = getQueryContext(entityType, property, propertyType, n, true);
try (IndexHits<Node> indexHits = nodeIndex.query(property, queryContext))
  for (Node node : indexHits)

private static QueryContext getQueryContext(String entityType, String property, String type, int n, boolean reversed)
  NumericRangeQuery propertyQuery;
  int fieldType;
  switch (type)
    case GraphTypes.LONG:
      propertyQuery = NumericRangeQuery.newLongRange(property, Long.MIN_VALUE, Long.MAX_VALUE, true, true);
      fieldType = SortField.LONG;
    case GraphTypes.DOUBLE:
      propertyQuery = NumericRangeQuery.newDoubleRange(property, Double.MIN_VALUE, Double.MAX_VALUE, true, true);
      fieldType = SortField.DOUBLE;
    case GraphTypes.FLOAT:
      propertyQuery = NumericRangeQuery.newFloatRange(property, Float.MIN_VALUE, Float.MAX_VALUE, true, true);
      fieldType = SortField.FLOAT;
    case GraphTypes.INT:
      propertyQuery = NumericRangeQuery.newIntRange(property, Integer.MIN_VALUE, Integer.MAX_VALUE, true, true);
      fieldType = SortField.INT;
      throw new IllegalArgumentException("Cannot create NumericRangeQuery for type: " + type);
  Query query;
  if (entityType == null)
    query = propertyQuery;
    TermQuery entityTypeQuery = new TermQuery(new Term("EntityType", entityType));
    BooleanQuery booleanQuery = new BooleanQuery();
    booleanQuery.add(entityTypeQuery, BooleanClause.Occur.MUST);
    booleanQuery.add(propertyQuery, BooleanClause.Occur.MUST);
    query = booleanQuery;
  Sort sorting = new Sort(new SortField(property, fieldType, reversed));
  return new QueryContext(query).sort(sorting).top(n);