Skip to content

Commit 146a387

Browse files
committed
geometry特化接口完成
1 parent c78229b commit 146a387

17 files changed

+804
-30
lines changed

src/main/java/org/wowtools/neo4j/rtree/RtreeEditor.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
/**
1717
* rtree编辑器,此对象实例化时,会启动一个事务,并在索引上加写锁,所以务必在结束时调用close方法
18+
* 此对象非线程安全
1819
*
1920
* @author liuyu
2021
* @date 2021/12/24
@@ -223,4 +224,12 @@ public void close() {
223224
txCell.commit();
224225
writeLock.unlock();
225226
}
227+
228+
public RTree getrTree() {
229+
return rTree;
230+
}
231+
232+
public TxCell getTxCell() {
233+
return txCell;
234+
}
226235
}

src/main/java/org/wowtools/neo4j/rtree/RtreeIntersectsSearcher.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,4 +109,7 @@ public void intersects(RectNd bbox, Transaction tx, BooleanDataNodeVisitor visit
109109

110110
}
111111

112+
public long getMetadataNodeId() {
113+
return metadataNodeId;
114+
}
112115
}

src/main/java/org/wowtools/neo4j/rtree/RtreeNearestSearcher.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import org.wowtools.neo4j.rtree.internal.RtreeLock;
77
import org.wowtools.neo4j.rtree.internal.define.Labels;
88
import org.wowtools.neo4j.rtree.internal.define.Relationships;
9-
import org.wowtools.neo4j.rtree.internal.nearest.DistanceResult;
9+
import org.wowtools.neo4j.rtree.util.DistanceResult;
1010
import org.wowtools.neo4j.rtree.util.NearestNeighbour;
1111

1212
import java.util.Iterator;
@@ -19,7 +19,7 @@
1919
* @author liuyu
2020
* @date 2021/12/27
2121
*/
22-
public class RtreeNearestSearcher {
22+
public class RtreeNearestSearcher<T extends DistanceResult> {
2323

2424
private final long metadataNodeId;
2525
private final Lock readLock;
@@ -38,7 +38,7 @@ private RtreeNearestSearcher(long metadataNodeId, Lock readLock) {
3838
* @param name 索引名
3939
* @return
4040
*/
41-
public static RtreeNearestSearcher get(Transaction tx, String name) {
41+
public static RtreeNearestSearcher get(Transaction tx, String name) {
4242
Node metadataNode = tx.findNode(Labels.METADATA, "name", name);
4343
if (null == metadataNode) {
4444
throw new RuntimeException("索引 " + name + " 不存在");
@@ -57,7 +57,7 @@ public static RtreeNearestSearcher get(Transaction tx, String name) {
5757
* @param tx 事务 此事务需要在外部手动关闭
5858
* @return
5959
*/
60-
public List<DistanceResult> nearest(NearestNeighbour nearestNeighbour, Transaction tx) {
60+
public List<T> nearest(NearestNeighbour<T> nearestNeighbour, Transaction tx) {
6161
readLock.lock();
6262
try {
6363
Node metadataNode = tx.getNodeById(metadataNodeId);
@@ -66,7 +66,7 @@ public List<DistanceResult> nearest(NearestNeighbour nearestNeighbour, Transacti
6666
return List.of();
6767
}
6868
Node root = iterator.next().getEndNode();
69-
List<DistanceResult> res = nearestNeighbour.find(root);
69+
List<T> res = nearestNeighbour.find(root);
7070
return res;
7171
} finally {
7272
readLock.unlock();
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package org.wowtools.neo4j.rtree.geometry2d;
2+
3+
import org.locationtech.jts.geom.Geometry;
4+
5+
/**
6+
* geometry数据节点访问器,返回true时,终止接下来的遍历
7+
*
8+
* @author liuyu
9+
* @date 2021/12/24
10+
*/
11+
@FunctionalInterface
12+
public interface BooleanGeometryDataNodeVisitor {
13+
14+
/**
15+
* 访问到数据节点时触发此方法
16+
*
17+
* @param nodeId 数据节点neo4j id
18+
* @param geometry 数据节点的geometry,由于空间计算时要使用一次,这里就直接把geometry返回了,避免重复的wkb转geometry
19+
* @return 返回true时,终止接下来的遍历
20+
*/
21+
boolean visit(long nodeId, Geometry geometry);
22+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package org.wowtools.neo4j.rtree.geometry2d;
2+
3+
import org.locationtech.jts.geom.GeometryFactory;
4+
5+
/**
6+
* @author liuyu
7+
* @date 2021/12/31
8+
*/
9+
class Constant {
10+
11+
public static final GeometryFactory geometryFactory = new GeometryFactory();
12+
13+
public static final String geometryNameKey = "geometryName";
14+
}
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
package org.wowtools.neo4j.rtree.geometry2d;
2+
3+
import org.locationtech.jts.geom.Geometry;
4+
import org.neo4j.graphdb.GraphDatabaseService;
5+
import org.neo4j.graphdb.Node;
6+
import org.wowtools.neo4j.rtree.RtreeEditor;
7+
import org.wowtools.neo4j.rtree.pojo.RectNd;
8+
import org.wowtools.neo4j.rtree.util.TxCell;
9+
import org.wowtools.neo4j.rtree.util.VoidDataNodeVisitor;
10+
11+
/**
12+
* 二维geometry rtree编辑器,此对象实例化时,会启动一个事务,并在索引上加写锁,所以务必在结束时调用close方法
13+
*
14+
* @author liuyu
15+
* @date 2021/12/28
16+
*/
17+
public class Geometry2dRtreeEditor implements AutoCloseable {
18+
19+
private final RtreeEditor rtreeEditor;
20+
21+
private Geometry2dRtreeEditor(RtreeEditor rtreeEditor) {
22+
this.rtreeEditor = rtreeEditor;
23+
}
24+
25+
/**
26+
* 获取索引
27+
*
28+
* @param graphdb neo4j db
29+
* @param commitLimit 操作达到多少个顶点时执行提交操作
30+
* @param name 索引名
31+
* @return
32+
*/
33+
public static Geometry2dRtreeEditor get(GraphDatabaseService graphdb, int commitLimit, String name) {
34+
RtreeEditor rtreeEditor = RtreeEditor.get(graphdb, commitLimit, name);
35+
try {
36+
Geometry2dRtreeEditor geometry2dRtreeEditor = new Geometry2dRtreeEditor(rtreeEditor);
37+
return geometry2dRtreeEditor;
38+
} catch (Exception e) {
39+
throw new RuntimeException(e);
40+
41+
}
42+
}
43+
44+
45+
/**
46+
* 新建索引
47+
*
48+
* @param graphdb neo4j db
49+
* @param commitLimit 操作达到多少个顶点时执行提交操作
50+
* @param name 索引名
51+
* @param mMin 索引中每个节点最小子节点数
52+
* @param mMax 索引中每个节点最大子节点数
53+
* @param geometryName dataNode中geometry字段名
54+
* @return
55+
*/
56+
public static Geometry2dRtreeEditor create(GraphDatabaseService graphdb, int commitLimit, String name, int mMin, int mMax,
57+
String geometryName) {
58+
RtreeEditor rtreeEditor = RtreeEditor.create(graphdb, commitLimit, name, mMin, mMax);
59+
try {
60+
long metadataNodeId = rtreeEditor.getrTree().getMetadataNodeId();
61+
Node metadataNode = rtreeEditor.getTxCell().getTx().getNodeById(metadataNodeId);
62+
metadataNode.setProperty(Constant.geometryNameKey, geometryName);
63+
Geometry2dRtreeEditor geometry2dRtreeEditor = new Geometry2dRtreeEditor(rtreeEditor);
64+
return geometry2dRtreeEditor;
65+
} catch (Exception e) {
66+
throw new RuntimeException(e);
67+
68+
}
69+
}
70+
71+
72+
/**
73+
* 若指定名称的索引存在,获取索引,若不存在,则新建一个
74+
*
75+
* @param graphdb neo4j db
76+
* @param commitLimit 操作达到多少个顶点时执行提交操作
77+
* @param name 索引名
78+
* @param mMin 索引中每个节点最小子节点数,如索引已存在则使用现有值,此输入值失效
79+
* @param mMax 索引中每个节点最大子节点数,如索引已存在则使用现有值,此输入值失效
80+
* @param geometryName dataNode中geometry字段名,如索引已存在则使用现有值,此输入值失效
81+
* @return RtreeEditor
82+
*/
83+
public static Geometry2dRtreeEditor getOrCreate(GraphDatabaseService graphdb, int commitLimit, String name, int mMin, int mMax,
84+
String geometryName) {
85+
RtreeEditor rtreeEditor = RtreeEditor.getOrCreate(graphdb, commitLimit, name, mMin, mMax);
86+
try {
87+
long metadataNodeId = rtreeEditor.getrTree().getMetadataNodeId();
88+
Node metadataNode = rtreeEditor.getTxCell().getTx().getNodeById(metadataNodeId);
89+
if (!metadataNode.hasProperty(Constant.geometryNameKey)) {
90+
metadataNode.setProperty(Constant.geometryNameKey, geometryName);
91+
}
92+
Geometry2dRtreeEditor geometry2dRtreeEditor = new Geometry2dRtreeEditor(rtreeEditor);
93+
return geometry2dRtreeEditor;
94+
} catch (Exception e) {
95+
rtreeEditor.close();
96+
throw new RuntimeException(e);
97+
}
98+
}
99+
100+
/**
101+
* 删除索引
102+
*
103+
* @param graphdb neo4j db
104+
* @param name 索引名
105+
* @param dataNodeVisitor 数据节点访问器,具体实现遇到数据节点该如何处置(例如将数据节点删除)
106+
*/
107+
public static void drop(GraphDatabaseService graphdb, String name, VoidDataNodeVisitor dataNodeVisitor) {
108+
RtreeEditor.drop(graphdb, name, dataNodeVisitor);
109+
}
110+
111+
112+
/**
113+
* 向索引中添加数据
114+
*
115+
* @param dataNodeId 数据节点neo4j id
116+
* @param geometry 数据节点geometry
117+
*/
118+
public void add(long dataNodeId, Geometry geometry) {
119+
RectNd rectNd = GeometryBbox.getBbox(geometry).toRect2d();
120+
rectNd.setDataNodeId(dataNodeId);
121+
rtreeEditor.add(rectNd);
122+
}
123+
124+
/**
125+
* 从索引中移除数据,注意不会删除数据节点,如需删除或其它操作应在自身业务代码中实现
126+
*
127+
* @param dataNodeId 被移除的数据节点neo4j id
128+
* @param geometry 被移除的数据节点geometry
129+
*/
130+
public void remove(long dataNodeId, Geometry geometry) {
131+
RectNd rectNd = GeometryBbox.getBbox(geometry).toRect2d();
132+
rectNd.setDataNodeId(dataNodeId);
133+
rtreeEditor.remove(rectNd);
134+
}
135+
136+
/**
137+
* 修改现有数据
138+
*
139+
* @param dataNodeId 数据节点neo4j id
140+
* @param oldGeometry 旧的的geometry
141+
* @param newGeometry 修改后的geometry
142+
*/
143+
public void update(long dataNodeId, Geometry oldGeometry, Geometry newGeometry) {
144+
RectNd oldRectNd = GeometryBbox.getBbox(oldGeometry).toRect2d();
145+
oldRectNd.setDataNodeId(dataNodeId);
146+
RectNd newRectNd = GeometryBbox.getBbox(newGeometry).toRect2d();
147+
newRectNd.setDataNodeId(dataNodeId);
148+
rtreeEditor.update(oldRectNd, newRectNd);
149+
}
150+
151+
@Override
152+
public void close() {
153+
rtreeEditor.close();
154+
}
155+
156+
public TxCell getTxCell() {
157+
return rtreeEditor.getTxCell();
158+
}
159+
}

0 commit comments

Comments
 (0)