use of org.neo4j.cypherdsl.core.Node in project openk9 by smclab.
the class GetOrAddEntitiesConsumer method apply.
public Mono<ObjectNode> apply(ObjectNode objectNode) {
return Mono.defer(() -> {
ObjectNode datasourceContextJson = objectNode.get("datasourceContext").toObjectNode();
long datasourceId = datasourceContextJson.get("datasource").get("datasourceId").asLong();
long tenantId = datasourceContextJson.get("tenant").get("tenantId").asLong();
JsonNode entities = objectNode.remove("entities");
Mono<ArrayNode> entitiesField;
if (entities.size() == 0) {
entitiesField = Mono.just(_jsonFactory.createArrayNode());
} else {
ObjectNode responseJson = _jsonFactory.createObjectNode();
responseJson.put("entities", entities);
responseJson.put("tenantId", tenantId);
responseJson.put("datasourceId", datasourceId);
Request request = _jsonFactory.fromJson(responseJson.toString(), Request.class);
List<RequestContext> requestContextList = request.getEntities().stream().map(entityRequest -> RequestContext.builder().current(entityRequest).tenantId(request.getTenantId()).datasourceId(request.getDatasourceId()).rest(request.getEntities().stream().filter(er -> er != entityRequest).collect(Collectors.toList())).build()).collect(Collectors.toList());
Mono<List<EntityContext>> disambiguateListMono = GetOrAddEntities.stopWatch("disambiguate-all-entities", Flux.fromIterable(requestContextList).flatMap(requestContext -> GetOrAddEntities.stopWatch("disambiguate-" + requestContext.getCurrent().getName(), Mono.<EntityContext>create(fluxSink -> _startDisambiguation.disambiguate(requestContext, fluxSink)))).collectList());
Mono<ResponseList> writeRelations = disambiguateListMono.flatMap(entityContexts -> GetOrAddEntities.stopWatch("write-relations", writeRelations(entityContexts)));
Mono<ResponseList> responseListWrapper = _transactional ? _graphClient.makeTransactional(writeRelations) : writeRelations;
entitiesField = responseListWrapper.map(responseListDTO -> {
List<Response> responseList = responseListDTO.getResponse();
ArrayNode entitiesArrayNode = entities.toArrayNode();
ArrayNode arrayNode = _jsonFactory.createArrayNode();
for (JsonNode node : entitiesArrayNode) {
Optional<Response> responseOptional = responseList.stream().filter(response -> node.get("tmpId").asLong() == response.getTmpId()).findFirst();
if (responseOptional.isPresent()) {
Entity entity = responseOptional.get().getEntity();
ObjectNode result = _jsonFactory.createObjectNode();
result.put("entityType", entity.getType());
result.put("id", entity.getId());
result.put("context", node.get("context"));
arrayNode.add(result);
}
}
return arrayNode;
});
}
return entitiesField.map(entitiesArray -> {
ObjectNode payload = objectNode.get("payload").toObjectNode();
payload.set("entities", entitiesArray);
return objectNode;
}).timeout(Duration.ofSeconds(_timeout), Mono.error(new TimeoutException("timeout on entities count: " + entities.size() + " (Did not observe any item or terminal signal within " + Duration.ofSeconds(_timeout).toMillis() + "ms)")));
});
}
use of org.neo4j.cypherdsl.core.Node in project openk9 by smclab.
the class GetOrAddEntitiesConsumer method writeRelations.
public Mono<ResponseList> writeRelations(List<EntityContext> entityContext) {
return Mono.defer(() -> {
List<Statement> statementList = new ArrayList<>();
for (EntityContext context : entityContext) {
EntityRequest entityRequest = context.getEntityRequest();
List<RelationRequest> relations = entityRequest.getRelations();
if (relations == null || relations.isEmpty()) {
continue;
}
Entity currentEntity = context.getEntity();
List<Tuple2<String, Entity>> entityRelations = entityContext.stream().flatMap(entry -> {
for (RelationRequest relation : relations) {
if (entry.getEntityRequest().getTmpId() == relation.getTo()) {
return Stream.of(Tuples.of(relation.getName(), entry.getEntity()));
}
}
return Stream.empty();
}).collect(Collectors.toList());
Node currentEntityNode = Cypher.node(currentEntity.getType()).named("a");
List<Statement> currentStatementList = entityRelations.stream().map(t2 -> {
Entity entityRelation = t2.getT2();
Node entityRelationNode = Cypher.node(entityRelation.getType()).named("b");
return Cypher.match(currentEntityNode, entityRelationNode).where(Functions.id(currentEntityNode).eq(literalOf(currentEntity.getId())).and(Functions.id(entityRelationNode).eq(literalOf(entityRelation.getId())))).merge(currentEntityNode.relationshipTo(entityRelationNode, t2.getT1())).build();
}).collect(Collectors.toList());
statementList.addAll(currentStatementList);
}
List<Response> response = entityContext.stream().map(context -> Response.builder().entity(Entity.builder().name(context.getEntity().getName()).id(context.getEntity().getId()).tenantId(context.getEntity().getTenantId()).type(context.getEntity().getType()).build()).tmpId(context.getEntityRequest().getTmpId()).build()).collect(Collectors.toList());
if (statementList.size() > 1) {
return _graphClient.write(Cypher.unionAll(statementList.toArray(new Statement[0]))).then(Mono.just(ResponseList.of("", response)));
} else if (statementList.size() == 1) {
return _graphClient.write(statementList.get(0)).then(Mono.just(ResponseList.of("", response)));
} else {
return Mono.just(ResponseList.of("", response));
}
});
}
use of org.neo4j.cypherdsl.core.Node in project openk9 by smclab.
the class CreateEntitiesRunnable method _getEntityGraphs.
private List<EntityGraph> _getEntityGraphs(EntityGraphService entityGraphService, List<EntityIndex> entityRequestList, int minHops, int maxHops, String currentEntityRequestType, List<EntityGraph> result) {
if (_log.isDebugEnabled()) {
_log.debug("disambiguating with search entity with type " + currentEntityRequestType);
}
Statement[] statements = new Statement[entityRequestList.size()];
for (int i = 0; i < entityRequestList.size(); i++) {
EntityIndex entityRequest = entityRequestList.get(i);
Node nodeEntity = Cypher.node(entityRequest.getType()).named("entity");
AliasedExpression entityAliased = nodeEntity.as("entity");
SymbolicName path = Cypher.name("path");
Property idProperty = entityAliased.getDelegate().property("id");
Statement statement = Cypher.match(nodeEntity).where(idProperty.eq(literalOf(entityRequest.getId()))).call("apoc.path.expand").withArgs(entityAliased.getDelegate(), literalOf(null), literalOf("-date"), literalOf(minHops), literalOf(maxHops)).yield(path).returning(Functions.last(Functions.nodes(path)).as("node"), Functions.size(Functions.nodes(path)).subtract(literalOf(1)).as("hops")).build();
statements[i] = statement;
}
if (statements.length == 1) {
Statement entityRequestListStatement = Cypher.call(statements[0]).returning("node", "hops").orderBy(Cypher.name("hops")).build();
result = entityGraphService.search(entityRequestListStatement);
} else if (statements.length > 1) {
Statement entityRequestListStatement = Cypher.call(Cypher.unionAll(statements)).returning("node", "hops").orderBy(Cypher.name("hops")).build();
result = entityGraphService.search(entityRequestListStatement);
}
return result;
}
use of org.neo4j.cypherdsl.core.Node in project openk9 by smclab.
the class GetOrAddEntities method _disambiguate.
private Mono<Entity> _disambiguate(List<DocumentEntityResponse> candidates, List<DocumentEntityResponse> entityRequestList, long tenantId, EntityRequest currentEntityRequest) {
Flux<Entity> entityFlux = Flux.empty();
String currentEntityRequestType = currentEntityRequest.getType();
if (_log.isDebugEnabled()) {
_log.debug(Arrays.toString(_uniqueEntities));
}
if (!candidates.isEmpty() && !_containsValue(_uniqueEntities, currentEntityRequestType)) {
if (_log.isDebugEnabled()) {
_log.debug("disambiguating with search entity with type " + currentEntityRequestType);
}
Statement[] statements = new Statement[entityRequestList.size()];
for (int i = 0; i < entityRequestList.size(); i++) {
DocumentEntityResponse entityRequest = entityRequestList.get(i);
Node nodeEntity = Cypher.node(entityRequest.getType()).named(ENTITY);
AliasedExpression entityAliased = nodeEntity.as(ENTITY);
SymbolicName path = Cypher.name(PATH);
Statement statement = Cypher.match(nodeEntity).where(Functions.id(nodeEntity).eq(literalOf(entityRequest.getId()))).call(APOC_PATH_EXPAND).withArgs(entityAliased.getDelegate(), literalOf(null), literalOf(_labelFilter), literalOf(_minHops), literalOf(_maxHops)).yield(path).returning(Functions.last(Functions.nodes(path)).as(NODE), Functions.size(Functions.nodes(path)).subtract(literalOf(1)).as(HOPS)).build();
statements[i] = statement;
}
if (statements.length == 1) {
Statement entityRequestListStatement = Cypher.call(statements[0]).returning(NODE, HOPS).orderBy(Cypher.name(HOPS)).build();
entityFlux = _entityGraphRepository.getEntities(entityRequestListStatement);
} else if (statements.length > 1) {
Statement entityRequestListStatement = Cypher.call(Cypher.unionAll(statements)).returning(NODE, HOPS).orderBy(Cypher.name(HOPS)).build();
entityFlux = _entityGraphRepository.getEntities(entityRequestListStatement);
}
}
if (candidates.size() == 1 && _containsValue(_uniqueEntities, currentEntityRequestType)) {
if (_log.isDebugEnabled()) {
_log.debug("disambiguating entity with type " + currentEntityRequestType);
}
DocumentEntityResponse candidate = candidates.get(0);
entityFlux = _entityGraphRepository.getEntity(candidate.getId()).flux();
}
return entityFlux.filter(entity -> candidates.stream().anyMatch(entity1 -> entity1.getId() == entity.getId())).next().switchIfEmpty(Mono.defer(() -> _entityGraphRepository.addEntity(tenantId, currentEntityRequest.getName(), currentEntityRequest.getType()).flatMap(entity -> {
if (_containsValue(_notIndexEntities, entity.getType())) {
return Mono.just(entity);
} else {
return _insertEntity(DocumentEntityRequest.builder().tenantId(entity.getTenantId()).name(entity.getName()).type(entity.getType()).id(entity.getId()).build()).thenReturn(entity);
}
})));
}
use of org.neo4j.cypherdsl.core.Node in project openk9 by smclab.
the class GetOrAddEntitiesHttpHandler method writeRelations.
public Mono<ResponseList> writeRelations(List<EntityContext> entityContext) {
return Mono.defer(() -> {
List<Statement> statementList = new ArrayList<>();
for (EntityContext context : entityContext) {
EntityRequest entityRequest = context.getEntityRequest();
List<RelationRequest> relations = entityRequest.getRelations();
if (relations == null || relations.isEmpty()) {
continue;
}
Entity currentEntity = context.getEntity();
List<Tuple2<String, Entity>> entityRelations = entityContext.stream().flatMap(entry -> {
for (RelationRequest relation : relations) {
if (entry.getEntityRequest().getTmpId() == relation.getTo()) {
return Stream.of(Tuples.of(relation.getName(), entry.getEntity()));
}
}
return Stream.empty();
}).collect(Collectors.toList());
Node currentEntityNode = Cypher.node(currentEntity.getType()).named("a");
List<Statement> currentStatementList = entityRelations.stream().map(t2 -> {
Entity entityRelation = t2.getT2();
Node entityRelationNode = Cypher.node(entityRelation.getType()).named("b");
return Cypher.match(currentEntityNode, entityRelationNode).where(Functions.id(currentEntityNode).eq(literalOf(currentEntity.getId())).and(Functions.id(entityRelationNode).eq(literalOf(entityRelation.getId())))).merge(currentEntityNode.relationshipTo(entityRelationNode, t2.getT1())).build();
}).collect(Collectors.toList());
statementList.addAll(currentStatementList);
}
List<Response> response = entityContext.stream().map(context -> Response.builder().entity(Entity.builder().name(context.getEntity().getName()).id(context.getEntity().getId()).tenantId(context.getEntity().getTenantId()).type(context.getEntity().getType()).build()).tmpId(context.getEntityRequest().getTmpId()).build()).collect(Collectors.toList());
if (statementList.size() > 1) {
return _graphClient.write(Cypher.unionAll(statementList.toArray(new Statement[0]))).then(Mono.just(ResponseList.of("", response)));
} else if (statementList.size() == 1) {
return _graphClient.write(statementList.get(0)).then(Mono.just(ResponseList.of("", response)));
} else {
return Mono.just(ResponseList.of("", response));
}
});
}
Aggregations