我在Sping Boot 中通过Neo4j查询实现CRUD操作时遇到了问题。
我的问题位于城市存储库、路线存储库、最短路径存储库和路线实体。
1)当我调用CityRepository的listAll和getById方法时,我得到了空城市名称,并在添加了如下所示的路线后列出了它的路线。
[
{
"id": "077d1b16-9a4b-4fb0-947b-52031774d949",
"name": "London",
"routes": []
},
{
"id": "077d1b16-9a4b-4fb0-947b-52031774d949",
"name": null,
"routes": [
{
"id": "6db5dd3f-085a-4d50-b025-4f0bee847fcf",
"from": "London",
"destination": "Berlin",
"departureTime": "9:00",
"arriveTime": "11:30",
"duration": 2.5
}
]
}
]
2)(编辑)添加City的任意一条路线,调用City的listAll后,得到截图中的这个结果。
第一次
下面是我的项目链接:Project
下面是 Postman 请求的集合:Link
以下是与我的问题相关的屏幕截图:Link
如何解决我的问题?
以下是我的实体,如下面所示的城市和路线。
城市
public class City {
@Id
@Property
private UUID id;
@Property
private String name;
@Relationship(type = "ROUTES", direction = Relationship.Direction.OUTGOING)
private Set<Route> routes = new HashSet<>();
public City(String name) {
this.name = name;
}
}
路线
public class Route {
@Id
@Property
private UUID id;
@Property
private String from;
@Property
private String destination;
@Property
private String departureTime;
@Property
private String arriveTime;
@Property
private Double duration;
}
这是我的CityRepository,如下所示。
public interface CityRepository extends Neo4jRepository<City,UUID> {
@Query("MATCH (city:City) OPTIONAL MATCH (city)-[r:ROUTES]->(route:Route) RETURN city, collect(r), collect(route)")
List<City> listAll();
@Query("MATCH (city:City {id: $cityId}) OPTIONAL MATCH (city)-[r:ROUTES]->(route:Route) RETURN city, collect(r), collect(route)")
City getById(UUID cityId);
@Query("MATCH (city:City {name: $cityName}) RETURN city")
City getByCityName(String cityName);
@Query("CREATE (city:City {id: randomUUID(), name: $cityName}) RETURN city")
City saveCity(String cityName);
@Query("MATCH (city:City {id: $cityId}) SET city.name = $cityName RETURN city")
City updateCity(UUID cityId, String cityName);
@Query("MATCH (city:City {id: $cityId}) DELETE city")
void deleteCity(UUID cityId);
}
下面显示的是我的RouteRepository。
public interface RouteRepository extends Neo4jRepository<Route,UUID> {
@Query("MATCH (city:City {id: $cityId})-[:ROUTES]->(route:Route) RETURN route")
List<Route> listAllByCityId(UUID cityId);
@Query("MATCH (route:Route {id: $routeId}) RETURN route")
Route getById(UUID routeId);
@Query("CREATE (city:City {id: $cityId})-[:ROUTES]->(route:Route {id: randomUUID(), from: $from, destination: $destination, departureTime: $departureTime," +
"arriveTime: $arriveTime, duration: $duration}) " +
"RETURN route")
Route saveRoute(UUID cityId, String from, String destination, String departureTime,
String arriveTime, double duration);
@Query("MATCH (city:City {id: $cityId})-[:ROUTES]->(route:Route {id: $routeId}) " +
"SET route.from = $from, route.destination = $destination,route.departureTime = $departureTime," +
"route.arriveTime = $arriveTime, route.duration = $duration RETURN route")
Route updateRoute(UUID cityId, UUID routeId, String from, String destination,String departureTime,
String arriveTime,double duration);
@Query("MATCH (city:City {id: $cityId})-[r:ROUTES]->(route:Route {id: $routeId}) DELETE r, route")
void deleteRoute(UUID cityId, UUID routeId);
}
2条答案
按热度按时间aij0ehis1#
第三次更新:自定义保存查询存在问题。使用
CREATE....
,Neo4j将始终创建新实体。创建至少与一个现有节点的新关系的最安全方法是匹配现有节点,然后在MERGE
语句中通过命名引用使用它。我更新了我的项目,但基本解决方案如下:第二次更新:好的,我更新了项目,现在开始在控制器级别上进行Web测试。请看一下并调整它,以重现我现在遗漏的错误。
我无法复制1和4,请查看
com.springshortpath.app.ApplicationWebTests#listCitiesWithRoutes
/com.springshortpath.app.ApplicationWebTests#listRoutesByCity
。对于2和3:查询模式要求至少定义一条路线。2如果还想得到没有路线的城市,你就必须选择匹配。
对于5:Spring Data Neo4j的存储库只能将实体定义作为返回类型来处理。如果您想使用Java驱动程序的类型,请使用SDN的
Neo4jClient
进行交互。SDN文档/ Neo4jClient更新到已编辑的问题:
删除进路:错误指出必须先移除相关性。正确的查询应该是
MATCH (city:City {id: $cityId})-[r:ROUTES]->(route:Route {id: $routeId}) DELETE r, route
对于无法通过城市UUID找到路线的情况:关系的方向是错误的,正确的一条是:
MATCH (city:City {id: $cityId})-[:ROUTES]->(route:Route) RETURN route
我无法重现其他问题,但我在您的存储库的一个分支中创建了我所理解的测试用例:https://github.com/meistermeier/SpringBootNeo4jShortestPath
老马回答:一般来说,我看到了
id
属性与节点的id
之间的误解。1)当我调用saveCity方法时,id值为0的值被添加了。我不知道为什么id被赋给0。
您将您的id定义为内部Neo4j id。
因此,SDN将在保存时将该值分配给id字段。节点的内部id将通过Cypher查询中的
id(node)
进行比较/检索。3)调用getCityById方法时,看不到任何结果
因此,查询
MATCH (city:City {id: $cityId}) RETURN city
将不查找正确的id字段,而是查找属性id
。2)当我调用listAll方法时,所有的值都被列出了(没有Route值,因为我无法添加Route)
如果您仍然在这里引用
CityRepository
,您将看不到任何Route
,因为您没有返回它们。将查询更改为MATCH (city:City)-[r:ROUTES]->(route:Route) RETURN city, collect(r), collect(route)
(或添加一个可选子句来获取路由,而不是要求模式),也会将Routes
添加到相应的Cities
中。4)当我调用updateCity方法时,我看不到任何结果。
这应该可以按预期工作,但我假设您说 * couldn 't see any result* 是指其他内容。它应该与方法
City getByCityName(String cityName)
(包括id属性更改)的结果相同。对于剩下的问题,我打赌这又是
node.id
属性与id(node)
的问题,所以基本上你有(n:City|Route...{id: $id})
的每个地方都应该变成(n:City|Route...) WHERE id(n) = $id
。67up9zun2#
请在下面找到我的答复。
1)当我调用saveCity方法时,id值为0的值被添加了。我不知道为什么id被赋给0。
我的回复:当你试图添加到数据库的id值从零开始,这是默认的零。当你添加第二个记录,然后id值将是1 ...类似的,当你添加第三个记录,id值将是2,依此类推。
2)当我调用listAll方法时,所有的值都被列出了(没有Route值,因为我无法添加Route)
我的回复:这是默认行为。
1.当我调用getCityById方法时,我看不到任何结果我的回复:您可以使用getById或getId
4)4)当我调用updateCity方法时,我看不到任何结果。
5)当我调用deleteCity方法时,我看到“City is deleted”,但当我调用listAll方法时,我看到该值。当我得到它时,删除方法无法工作。
6)当我调用saveRoute时,它被添加了,但是有一个id问题。当我调用City方法的listAll时,我看不到它的值。
7)当我调用getRouteById方法时,我看不到任何结果
8)当我调用listAll方法时,我看不到任何结果。
9)当我调用updateRoute方法时,我看不到任何结果。
10)当我调用deleteRoute方法时,我看到“Route is deleted”,但当我调用listAll方法时,我看不到任何结果。我不知道它是否被删除。
我的回复:对于4,5,6,7,8,9,我认为你没有提交或保存有关编程。提交操作后,只有结果将被保存或更新。