Getting spatial almost to work.

This commit is contained in:
Peter Neubauer
2011-10-21 16:49:10 +02:00
committed by Michael Hunger
parent 2c9c856b7c
commit 5759f0780f
13 changed files with 194 additions and 48 deletions

View File

@@ -27,7 +27,6 @@ import java.util.Collection;
import java.util.HashSet;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.neo4j.graphdb.DynamicRelationshipType;
@@ -154,12 +153,6 @@ public class IndexTest extends EntityTestBase {
@Indexed(indexType=IndexType.FULLTEXT, indexName = "InvalidIndexed")
String fullTextDefaultIndexName;
@Indexed(indexType=IndexType.POINT, indexName = "InvalidIndexed")
double[] latlon;
@Indexed(indexType=IndexType.POINT)
double[] latlonNoIndexName;
public void setFulltextNoIndexName(String fulltextNoIndexName) {
this.fulltextNoIndexName = fulltextNoIndexName;
}
@@ -173,22 +166,22 @@ public class IndexTest extends EntityTestBase {
static class InvalidSpatialIndexed {
@Indexed(indexType=IndexType.POINT, indexName = "InvalidSpatialIndexed")
double[] latlon;
String latlon;
@Indexed(indexType=IndexType.POINT)
double[] latlonNoIndexName;
String latlonNoIndexName;
@Indexed(indexType=IndexType.POINT, indexName = "pointLayer")
double[] latlonValid;
String latlonValid;
public void setLatlonNoIndexName(double[] latlonNoIndexName) {
public void setLatlonNoIndexName(String latlonNoIndexName) {
this.latlonNoIndexName = latlonNoIndexName;
}
public void setLatlon(double[] latlon) {
public void setLatlon(String latlon) {
this.latlon = latlon;
}
public void setLatlonValid(double[] latlonValid) {
public void setLatlonValid(String latlonValid) {
this.latlonValid = latlonValid;
}
}
@@ -197,7 +190,7 @@ public class IndexTest extends EntityTestBase {
@Transactional
public void indexAccessWithFullAndNoSpatialIndexNameShouldFail() {
InvalidSpatialIndexed invalidIndexed = persist(new InvalidSpatialIndexed());
double[] latlon = {15.0,65};
String latlon = "POINT (55 15)";
invalidIndexed.setLatlonNoIndexName(latlon);
}
@@ -205,16 +198,15 @@ public class IndexTest extends EntityTestBase {
@Transactional
public void indexAccessWithDefaultSpatialIndexNameShouldFail() {
InvalidSpatialIndexed invalidIndexed = persist(new InvalidSpatialIndexed());
double[] latlon = {15.0,65};
String latlon = "POINT (55 15)";
invalidIndexed.setLatlon( latlon);
}
@Test
@Ignore
@Transactional
public void indexAccessWithValidSpatialIndexName() {
InvalidSpatialIndexed invalidIndexed = persist(new InvalidSpatialIndexed());
double[] latlon = {15.0,65};
String latlon = "POINT (55 15)";
invalidIndexed.setLatlonValid( latlon);
}

View File

@@ -413,6 +413,18 @@
<version>${neo4j.spatial.version}</version>
<optional>true</optional>
</dependency-->
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-shell</artifactId>
<version>${neo4j.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-udc</artifactId>
<version>${neo4j.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-spatial</artifactId>

View File

@@ -128,6 +128,11 @@
<artifactId>neo4j-cypher</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-shell</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>

View File

@@ -16,6 +16,11 @@
package org.springframework.data.neo4j.repository;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.apache.lucene.search.NumericRangeQuery;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.NotFoundException;
@@ -34,11 +39,6 @@ import org.springframework.data.neo4j.support.Neo4jTemplate;
import org.springframework.data.neo4j.support.index.NoSuchIndexException;
import org.springframework.data.neo4j.support.index.NullReadableIndex;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
/**
* Repository like finder for Node and Relationship-Entities. Provides finder methods for direct access, access via {@link org.springframework.data.neo4j.core.TypeRepresentationStrategy}
* and indexing.
@@ -47,7 +47,14 @@ import java.util.List;
* @param <S> Type of backing state, either Node or Relationship
*/
@org.springframework.stereotype.Repository
public abstract class AbstractGraphRepository<S extends PropertyContainer, T> implements GraphRepository<T>, NamedIndexRepository<T> {
public abstract class AbstractGraphRepository<S extends PropertyContainer, T> implements GraphRepository<T>, NamedIndexRepository<T>, SpatialRepository<T> {
@Override
public ClosableIterable<T> findByBoundingBox( String indexName, double lowerLeftLat,
double lowerLeftLon, double upperRightLat, double upperRightLon )
{
return findAllByQuery( indexName, "bbox", String.format("[%f, %f, %f, %f]", lowerLeftLon, upperRightLon, lowerLeftLat, upperRightLat) );
}
public static final ClosableIterable EMPTY_CLOSABLE_ITERABLE = new ClosableIterable() {
@Override
public void close() {

View File

@@ -0,0 +1,33 @@
/**
* Copyright 2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.neo4j.repository;
import org.neo4j.helpers.collection.ClosableIterable;
/**
* @author mh
* @since 29.03.11
*/
public interface SpatialRepository<T> {
ClosableIterable<T> findByBoundingBox(String indexName, double lowerLeftLat,
double lowerLeftLon,
double upperRightLat,
double upperRightLon);
}

View File

@@ -136,7 +136,8 @@ public class DelegatingGraphDatabase implements GraphDatabase {
if (isNode(type)) {
if (indexManager.existsForNodes(indexName))
return (Index<T>) checkAndGetExistingIndex(indexName, indexType, indexManager.forNodes(indexName));
return (Index<T>) indexManager.forNodes(indexName, indexConfigFor(indexType));
Index<Node> index = indexManager.forNodes(indexName, indexConfigFor(indexType));
return (Index<T>) index;
} else {
if (indexManager.existsForRelationships(indexName))
return (Index<T>) checkAndGetExistingIndex(indexName, indexType, indexManager.forRelationships(indexName));

View File

@@ -35,7 +35,6 @@ public enum IndexType
SIMPLE{ public Map<String,String> getConfig() { return LuceneIndexImplementation.EXACT_CONFIG; } },
FULLTEXT { public Map<String,String> getConfig() { return LuceneIndexImplementation.FULLTEXT_CONFIG; } },
POINT { public Map<String,String> getConfig() { return MapUtil.stringMap(
IndexManager.PROVIDER, "spatial", "geometry_type" , "point") ; } };
IndexManager.PROVIDER, "spatial", "geometry_type" , "point","wkt","wkt") ; } };
public abstract Map<String, String>getConfig();
}

View File

@@ -20,6 +20,7 @@ import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.Node;
import org.springframework.data.neo4j.annotation.*;
import org.springframework.data.neo4j.fieldaccess.DynamicProperties;
import org.springframework.data.neo4j.support.index.IndexType;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
@@ -42,6 +43,9 @@ public class Person {
@Indexed
private String nickname;
@Indexed(indexType = IndexType.POINT, indexName="personLayer")
private String wkt;
@Max(100)
@Min(0)
@Indexed
@@ -159,6 +163,10 @@ public class Person {
public void setBoss(Person boss) {
this.boss = boss;
}
public void setLocation(String locationInWkt) {
this.wkt = locationInWkt;
}
@Override
public String toString() {

View File

@@ -16,6 +16,18 @@
package org.springframework.data.neo4j.repository;
import static java.util.Arrays.asList;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.internal.matchers.IsCollectionContaining.hasItem;
import static org.junit.internal.matchers.IsCollectionContaining.hasItems;
import static org.neo4j.helpers.collection.IteratorUtil.addToCollection;
import static org.neo4j.helpers.collection.IteratorUtil.asCollection;
import java.util.HashSet;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Before;
@@ -38,18 +50,6 @@ import org.springframework.test.context.transaction.BeforeTransaction;
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
import org.springframework.transaction.annotation.Transactional;
import java.util.HashSet;
import java.util.Map;
import static java.util.Arrays.asList;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.internal.matchers.IsCollectionContaining.hasItem;
import static org.junit.internal.matchers.IsCollectionContaining.hasItems;
import static org.neo4j.helpers.collection.IteratorUtil.addToCollection;
import static org.neo4j.helpers.collection.IteratorUtil.asCollection;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@TestExecutionListeners({CleanContextCacheTestExecutionListener.class, DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class})
@@ -88,6 +88,12 @@ public class GraphRepositoryTest {
assertThat(asCollection(teamMembers), hasItems(testTeam.michael, testTeam.david, testTeam.emil));
}
@Test
public void testFindIterableOfPersonWithQueryAnnotationSpatial() {
Iterable<Person> teamMembers = personRepository.findByBoundingBox( "personLayer", 55, 15, 57, 17 );
assertThat(asCollection(teamMembers), hasItems(testTeam.michael, testTeam.david, testTeam.emil));
}
@Test
public void testFindIterableOfPersonWithQueryAnnotationAndGremlin() {
Iterable<Person> teamMembers = personRepository.findAllTeamMembersGremlin(testTeam.sdg);

View File

@@ -34,7 +34,7 @@ import java.util.Map;
* @author Oliver Gierke
* @since 29.03.11
*/
public interface PersonRepository extends GraphRepository<Person>, NamedIndexRepository<Person> {
public interface PersonRepository extends GraphRepository<Person>, NamedIndexRepository<Person>, SpatialRepository<Person> {
@Query("start team=node({p_team}) match (team)-[:persons]->(member) return member")
Iterable<Person> findAllTeamMembers(@Param("p_team") Group team);
@@ -62,6 +62,7 @@ public interface PersonRepository extends GraphRepository<Person>, NamedIndexRep
@Query("start team=node({p_team}) match (team)-[:persons]->(member) return member")
Iterable<Person> findAllTeamMembersSorted(@Param("p_team") Group team, Sort sort);
// Derived queries
Iterable<Person> findByName(String name);
}

View File

@@ -0,0 +1,88 @@
/**
* Copyright 2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.neo4j.repository;
import static org.junit.Assert.assertThat;
import static org.junit.internal.matchers.IsCollectionContaining.hasItems;
import static org.neo4j.helpers.collection.IteratorUtil.asCollection;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.neo4j.model.Person;
import org.springframework.data.neo4j.support.Neo4jTemplate;
import org.springframework.data.neo4j.support.node.Neo4jHelper;
import org.springframework.test.context.CleanContextCacheTestExecutionListener;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import org.springframework.test.context.transaction.BeforeTransaction;
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({CleanContextCacheTestExecutionListener.class, DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class})
@ContextConfiguration(locations = {"classpath:org/springframework/data/neo4j/repository/GraphRepositoryTest-context.xml"})
@Transactional
public class SpatialGraphRepositoryTest {
protected final Log log = LogFactory.getLog(getClass());
@Autowired
private Neo4jTemplate neo4jTemplate;
@Autowired
private PersonRepository personRepository;
@Autowired
GroupRepository groupRepository;
@Autowired FriendshipRepository friendshipRepository;
@Autowired
PlatformTransactionManager transactionManager;
private TestTeam testTeam;
@BeforeTransaction
public void cleanDb() {
Neo4jHelper.cleanDb(neo4jTemplate);
}
@Before
public void setUp() throws Exception {
new TransactionTemplate(transactionManager).execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
testTeam = new TestTeam();
testTeam.createSDGTeam(personRepository, groupRepository,friendshipRepository);
}
});
}
@Test
public void testFindIterableOfPersonWithQueryAnnotationSpatial() {
Iterable<Person> teamMembers = personRepository.findByBoundingBox( "personLayer", 55, 15, 57, 17 );
assertThat(asCollection(teamMembers), hasItems(testTeam.michael, testTeam.david, testTeam.emil));
}
}

View File

@@ -42,9 +42,11 @@ public class TestTeam {
michael = new Person("Michael", 36);
michael.setBoss(emil);
michael.setPersonality(Personality.EXTROVERT);
michael.setLocation( "POINT(16 56)" );
david = new Person("David", 25);
david.setBoss(emil);
david.setLocation( "POINT (16 56)" );
friendShip = michael.knows(david);
friendShip.setYears(2);
sdg = new Group();

View File

@@ -7,16 +7,8 @@
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/data/neo4j http://www.springframework.org/schema/data/neo4j/spring-neo4j-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<context:annotation-config/>
<neo4j:config graphDatabaseService="graphDatabaseService"/>
<neo4j:repositories base-package="org.springframework.data.neo4j.repository"/>
<bean id="graphDatabaseService" class="org.neo4j.test.ImpermanentGraphDatabase" destroy-method="shutdown">
<constructor-arg>
<map>
<entry key="enable_shell"><value>true</value></entry>
</map>
</constructor-arg>
</bean>
<bean id="graphDatabaseService" class="org.neo4j.test.ImpermanentGraphDatabase" destroy-method="shutdown"/>
</beans>