Skip to content

Commit

Permalink
GH-4978 Index geosparql points using geo field (#4979)
Browse files Browse the repository at this point in the history
  • Loading branch information
hmottestad authored May 31, 2024
2 parents 3d218d9 + 2082613 commit 192b4ea
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,12 @@ private void indexShape(Object shape, String field) {
doc.add(f);
}
} else if (shape instanceof double[]) { // WKT:POINT
double point[] = (double[]) shape;
double[] point = (double[]) shape;

for (Field f : LatLonShape.createIndexableFields(GEO_FIELD_PREFIX + field, point[1],
point[0])) {
doc.add(f);
}
doc.add(new LatLonPoint(POINT_FIELD_PREFIX + field, point[1], point[0]));
} else if (shape instanceof Rectangle) { // WKT:ENVELOPE / RECTANGLE
Rectangle box = (Rectangle) shape;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@

import java.io.IOException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.function.Function;

import org.apache.lucene.analysis.en.EnglishAnalyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
Expand All @@ -39,12 +41,23 @@
import org.eclipse.rdf4j.common.concurrent.locks.Properties;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Literal;
import org.eclipse.rdf4j.model.Model;
import org.eclipse.rdf4j.model.Resource;
import org.eclipse.rdf4j.model.Statement;
import org.eclipse.rdf4j.model.Value;
import org.eclipse.rdf4j.model.ValueFactory;
import org.eclipse.rdf4j.model.base.CoreDatatype;
import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
import org.eclipse.rdf4j.model.impl.TreeModel;
import org.eclipse.rdf4j.model.vocabulary.GEO;
import org.eclipse.rdf4j.model.vocabulary.GEOF;
import org.eclipse.rdf4j.query.BindingSet;
import org.eclipse.rdf4j.query.TupleQuery;
import org.eclipse.rdf4j.query.TupleQueryResult;
import org.eclipse.rdf4j.repository.sail.SailRepository;
import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection;
import org.eclipse.rdf4j.repository.util.Repositories;
import org.eclipse.rdf4j.sail.evaluation.TupleFunctionEvaluationMode;
import org.eclipse.rdf4j.sail.lucene.LuceneSail;
import org.eclipse.rdf4j.sail.lucene.SearchFields;
import org.eclipse.rdf4j.sail.memory.MemoryStore;
Expand Down Expand Up @@ -478,4 +491,85 @@ private void assertNoStatement(Statement statement, Document document) {
* for(String notFound : toFind) { assertEquals("Was the expected text value '" + notFound + "' found?", true,
* false); } }
*/

@Test
public void geoSparqlQueryTest() {
final String prefix = "http://www.example.org/#";
final String prefixes = "PREFIX ex: <" + prefix + ">\n"
+ "PREFIX geof: <" + GEOF.NAMESPACE + ">\n"
+ "PREFIX geo: <" + CoreDatatype.GEO.NAMESPACE + ">\n"
+ "PREFIX uom: <http://www.opengis.net/def/uom/OGC/1.0/>\n";
Model data = new TreeModel();

IRI cp = vf.createIRI(prefix + "cp");
IRI bm = vf.createIRI(prefix + "bm");
IRI nkv = vf.createIRI(prefix + "nkv");

data.add(cp, GEO.AS_WKT, vf.createLiteral("Point(4.38436 45.44917)", CoreDatatype.GEO.WKT_LITERAL));
data.add(bm, GEO.AS_WKT, vf.createLiteral("Point(4.38311 45.45423)", CoreDatatype.GEO.WKT_LITERAL));
data.add(nkv, GEO.AS_WKT, vf.createLiteral("Point(4.87306 45.77903)", CoreDatatype.GEO.WKT_LITERAL));
data.add(vf.createIRI(prefix + "arp"), GEO.AS_WKT,
vf.createLiteral("Point(2.89271 42.69848)", CoreDatatype.GEO.WKT_LITERAL));

String polyVill = "POLYGON((4.864712 45.784405, 4.883165 45.787756, 4.889946 45.785781, 4.904881 45.767403, 4.900761 45.765487, 4.872093 45.770995, 4.86454 45.770457, 4.858789 45.770277, 4.859905 45.784644, 4.864712 45.784405))";
String polySain = "POLYGON((4.380627 45.463983, 4.400539 45.462177, 4.428349 45.436286, 4.399509 45.411346, 4.374447 45.426528, 4.370499 45.450618, 4.380627 45.463983))";

SailRepository m1 = new SailRepository(new MemoryStore());
LuceneSail lc = new LuceneSail();
lc.setBaseSail(new MemoryStore());
lc.setParameter(LuceneSail.WKT_FIELDS, GEO.AS_WKT.toString());
lc.setLuceneIndex(index);
lc.setEvaluationMode(TupleFunctionEvaluationMode.NATIVE);
SailRepository m2 = new SailRepository(lc);

// add test data
Repositories.consume(m1, conn -> conn.add(data));
Repositories.consume(m2, conn -> conn.add(data));

lc.reindex();

Function<TupleQueryResult, Set<Value>> toval = (res) -> {
Set<Value> list = new HashSet<>();
while (res.hasNext()) {
BindingSet next = res.next();
list.add(next.getValue("v"));
}
return list;
};

// test queries

String q0 = prefixes
+ "SELECT * {\n"
+ " ?v geo:asWKT ?loc .\n"
+ " FILTER(geof:distance(\"Point(4.386914 45.440637)\"^^geo:wktLiteral, ?loc, uom:metre) < 10000) \n"
+ "}\n";
Set<Value> q0ex = Set.of(bm, cp);

String q1 = prefixes
+ "SELECT * {\n"
+ " ?v geo:asWKT ?loc .\n"
+ " FILTER(geof:ehContains(\"" + polySain + "\"^^geo:wktLiteral, ?loc)) \n"
+ "}\n";
Set<Value> q1ex = Set.of(bm, cp);

String q2 = prefixes
+ "SELECT * {\n"
+ " ?v geo:asWKT ?loc .\n"
+ " FILTER(geof:ehContains(\"" + polyVill + "\"^^geo:wktLiteral, ?loc)) \n"
+ "}\n";
Set<Value> q2ex = Set.of(nkv);

Set<Value> nlcq0 = Repositories.tupleQuery(m1, q0, toval);
Set<Value> nlcq1 = Repositories.tupleQuery(m1, q1, toval);
Set<Value> nlcq2 = Repositories.tupleQuery(m1, q2, toval);

assertEquals(q0ex, nlcq0);
assertEquals(q1ex, nlcq1);
assertEquals(q2ex, nlcq2);

assertEquals(nlcq0, Repositories.tupleQuery(m2, q0, toval));
assertEquals(nlcq1, Repositories.tupleQuery(m2, q1, toval));
assertEquals(nlcq2, Repositories.tupleQuery(m2, q2, toval));
}
}

0 comments on commit 192b4ea

Please sign in to comment.