Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.
02-17-2021 04:54 PM
I'm trying to execute a custom cypher query in Spring boot reactive app but always getting an empty output. I have tried executing the query in neo4j browser and I'm able to get an anticipated result. I have found similar kind of example here but it is with Neo4JClient not with Neo4jReactiveClient
When I tried debugging the code in MyDbClient -> getTeamWithPlayers the pointer is not entering into query.mappedBy function.
API
GetMapping("/teamAndPlayes/{teamId}")
public Mono<TeamWithPlayers> updateEventStatus(@RequestHeader("uid") String uid, @PathVariable Long teamId) {
return myDbClient.getTeamWithPlayers(teamId);
}
ReactiveNeo4jClient Implementation
@Component
@RequiredArgsConstructor
public class MyDbClient {
private final ReactiveNeo4jClient client;
public Mono<TeamWithPlayers> getTeamWithPlayers(Long teamId) {
String query = "Match (team:Team) where id(team) =$teamId match (team)-[:REL{is:'TEAM'}]->(u:User) "
+ "optional Match (u) -[role:ROLE]->(team) "
+ "with team, COLLECT(u) as users, collect({uid: u.uid, role : role.is}) as roles "
+ "return team {id:id(team), .name, .description, .location, .emailAddress, .profileImgURL, .createdOn, users: users, roles: roles}";
return client.query(query).bind(teamId).to("teamId").fetchAs(TeamWithPlayers.class)
.mappedBy((TypeSystem ts, Record r) -> {
Value team = r.get("team");
List<User> users = team.get("users").asList(u -> User.builder()
.firstName(u.get("firstName").asString()).lastName(u.get("lastName").asString()).build());
List<PlayerRole> roles = team.get("roles").asList(pr -> PlayerRole.builder()
.uid(pr.get("uid").asString()).role(pr.get("role").asString()).build());
return TeamWithPlayers.builder().id(team.get("id").asLong()).name(team.get("name").asString())
.description(team.get("description").asString()).location(team.get("location").asString())
.emailAddress(team.get("emailAddress").asString())
.createdOn(team.get("createdOn").asLocalDateTime()).users(users).roles(roles).build();
}).one();
}
}
@Data
@Builder
@ToString
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class TeamWithPlayers {
private Long id;
private String name;
private String description;
private String location;
private String emailAddress;
private String profileImgURL;
private LocalDateTime createdOn;
List<User> users;
List<PlayerRole> roles;
}
@Node
@Data
@ToString
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class User implements Entity {
@Id
@GeneratedValue
private Long id;
private String uid;
private String firstName;
private String lastName;
private String emailAddress;
private String profileImgURL;
private LocalDateTime updatedAt;
private LocalDateTime createdAt;
private LocalDateTime lastLoggedInAt;
}
@Data
@ToString
@Builder
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class PlayerRole {
String uid;
String role;
}
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-neo4j</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
Not sure what wrong in my approach
02-18-2021 02:05 AM
Not entering the mapping is a pretty good sign that there aren't any records to process. Your result is empty.
Given this even simpler example but keeping the structure of your HTTP endpoint:
@RestController
public class SomeController {
private final ReactiveNeo4jClient client;
public SomeController(@Autowired ReactiveNeo4jClient client) {
this.client = client;
}
@GetMapping("/teamAndPlayes/{name}")
public Mono<Thing> updateEventStatus(@PathVariable String name) {
String query = "Match (thing:Thing) where thing.name = $name return thing {.name}";
return client.query(query).bind(name).to("name").fetchAs(Thing.class)
.mappedBy((TypeSystem ts, org.neo4j.driver.Record r) -> {
Value thing = r.get("thing");
return Thing.builder().name(thing.get("name").asString()).build();
}).one();
}
@Data
@Builder
public static class Thing {
private final String name;
}
}
works fine for a given Thing
with a certain name
.
02-18-2021 11:22 AM
Thank you very much Meier.. your below comment helped me think in right direction.
Not entering the mapping is a pretty good sign that there aren't any records to process
I was in assumption that the ReactiveNeo4jClient will be connected to the database (Scoveer) based on the configuration
spring.data.neo4j.database=Scoveer
spring.neo4j.uri=bolt://localhost:11006
spring.neo4j.authentication.username=neo4j
spring.neo4j.authentication.password=******
spring.data.neo4j.repositories.type=reactive
But by default it is connecting to neo4j default Db hence I was getting empty result
I have added below code to fix the issue. check .in(database()) the snippet
return client.query(query).in(database()).bind(teamId).to("teamId").fetchAs(TeamWithPlayers.class)
.mappedBy((TypeSystem ts, Record r) -> {
.....
}).one();
private String database() {
return databaseSelectionProvider.getDatabaseSelection().getValue();
}
@Bean
DatabaseSelectionProvider databaseSelectionProvider(@Value("${spring.data.neo4j.database}") String database) {
return () -> {
String neo4jVersion = System.getenv("NEO4J_VERSION");
if (neo4jVersion == null || neo4jVersion.startsWith("4")) {
return DatabaseSelection.byName(database);
}
return DatabaseSelection.undecided();
};
}
Check here for more detailed example.
@gerrit.meier Why don't we align both spring data repositories and Neo4jClients with same behaviour by default connecting to configure database (spring.data.neo4j.database) ??
In current implementation by default Repositories are connecting to spring.data.neo4j.database and Neo4JClients are connecting default neo4j DB.
Thank you
02-19-2021 04:17 AM
We have now an issue to track for the DatabaseSelectionProvider
support in the (Reactive)Neo4jClient Support for database selection in (Reactive)Neo4jClient · Issue #2159 · spring-projects/spring-data-...
02-19-2021 07:36 AM
Ok, Thank you for the update!
All the sessions of the conference are now available online