springboot + neo4j 功能使用

集成

添加依赖

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-neo4j</artifactId></dependency>
spring:# neo4j 图数据库neo4j:uri: bolt://localhost:7687authentication:username: neo4jpassword: admin# 指定数据库data:neo4j:database: neo4j

如果和数据库一起集成,需要配置多数据源事务,不然事务会失效

import org.neo4j.driver.Driver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.neo4j.core.transaction.Neo4jTransactionManager;
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
import org.springframework.data.transaction.ChainedTransactionManager;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;import javax.sql.DataSource;/*** 配置neo4j 和 mysql 事务* 1、@EnableNeo4jRepositories 用于扫描指定包下的repository* 2、@EntityScan 用于扫描 neo4j实体类*/
@Configuration
@EnableTransactionManagement
@EnableNeo4jRepositories(basePackages = {"com.graph.repository"})
@EntityScan(basePackages = {"com.graph.model.neo4j"})
public class Neo4jConfig {/*** 此处为了修改默认事务,必须改。* 加载了Neo4J依赖库之后,transactionManager变成Neo4jTransactionManager** @param dataSource 数据源* @return*/@Bean("transactionManager")@Primarypublic DataSourceTransactionManager transactionManager(DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}/*** Neo4J的事务管理** @param driver* @return*/@Bean("neo4jTransactionManager")public Neo4jTransactionManager neo4jTransactionManager(Driver driver) {return new Neo4jTransactionManager(driver);}/*** 需要使用多种事务时** @param neo4jTransactionManager* @param mysqlTransactionManager* @return*/@Autowired@Bean(name = "multiTransactionManager")public PlatformTransactionManager multiTransactionManager(Neo4jTransactionManager neo4jTransactionManager,DataSourceTransactionManager mysqlTransactionManager) {return new ChainedTransactionManager(neo4jTransactionManager, mysqlTransactionManager);}
}

1.使用Neo4jRepository 进行查询,可以使用jpa进行查询

import lombok.Data;
import org.springframework.data.neo4j.core.schema.GeneratedValue;
import org.springframework.data.neo4j.core.schema.Id;
import org.springframework.data.neo4j.core.schema.Node;
import org.springframework.data.neo4j.core.schema.Property;/*** 文献** @author kou*/
@Data
@Node(labels = "文献")
public class Literature {@Id@GeneratedValueprivate Long id;@Property(name = "name")private String name;/*** 文件路径*/@Property(name = "url")private String url;}
import com.haiwanyoutian.hai.graph.model.neo4j.Literature;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.neo4j.repository.Neo4jRepository;
import org.springframework.data.neo4j.repository.query.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;import java.util.List;/*** 文献 持久层** @author kou*/
@Repository
public interface LiteratureRepository extends Neo4jRepository<Literature, Long> {/*** 按名称查询** @param name 名称* @return 结果*/
//	@Query("MATCH(p:`文献`{name:$name}) return p")List<Literature> findByName(@Param("name") String name);/*** 按名称模糊查询** @param name 名称* @return 结果*/List<Literature> findByNameLike(@Param("name") String name);/*** 分页查询** @param name     名称* @param pageable 分页条件* @return 结果*/Page<Literature> findByNameLike(@Param("name") String name, Pageable pageable);@Query(value = "match (n:`文献`) " +" WHERE (n.name CONTAINS $keyword" +" or n.full_paper_outline_en CONTAINS $keyword" +" or n.full_paper_outline_zh CONTAINS $keyword" +" or n.full_paper_summary_en CONTAINS $keyword" +" or n.full_paper_summary_zh CONTAINS $keyword) " +" return n" +" SKIP $skip LIMIT $limit ",countQuery = "match (n:`文献`) " +" WHERE (n.name CONTAINS $keyword" +" or n.full_paper_outline_en CONTAINS $keyword" +" or n.full_paper_outline_zh CONTAINS $keyword" +" or n.full_paper_summary_en CONTAINS $keyword" +" or n.full_paper_summary_zh CONTAINS $keyword) " +"return count(*)")Page<Literature> findByKeyword(@Param("keyword") String keyword, @Param("pageable") Pageable pageable);/*** 查询关系** @param name 名称* @return 结果*/@Query("MATCH(n:`文献`{name:$name}) return (n)-[]-()")Literature queryLiteratureRelation(@Param("name") String name);/*** 查询关键字期刊** @param keyword 关键字* @param limit   数量* @return 结果*/@Deprecated@Query("match(n) where labels(n) in [['文献'],['作者']]  " +"with n, [x in keys(n) WHERE n[x]=~'.*'+$keyword+'.*'] as dm " +"where size(dm) > 0 " +"with n " +"LIMIT $limit " +"match p=(n)-[]-(k) " +"return p ")List<Literature> queryLiteratureByKeyword(@Param("keyword") String keyword, @Param("limit") Integer limit);}

2. 使用cypher进行查询

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;import java.util.List;/*** 知识接口实现类** @author kou*/
@Slf4j
@RequiredArgsConstructor
@Service
public class LiteratureServiceImpl implements ILiteratureService {private final LiteratureRepository literatureRepository;private final INeo4jService neo4jService;/*** 文献搜索** @param keyword  关键字* @param pageable 分页查询* @return 结果*/@Overridepublic Page<Literature> search(String keyword, Pageable pageable) {if (StringUtils.isNotBlank(keyword)) {// return literatureRepository.findByNameLike(keyword, pageable);return literatureRepository.findByKeyword(keyword, pageable);}return literatureRepository.findAll(pageable);}/*** 文献图库搜索** @param keyword 关键字* @param limit   数量* @return 结果*/@Overridepublic Object graphSearch(String keyword, Integer limit) {StringBuffer sql = new StringBuffer();if (StringUtils.isNotBlank(keyword)) {sql.append("match(n) where labels(n) in [['文献'],['作者']] ");sql.append("with n, [x in keys(n) WHERE n[x]=~'.*").append(keyword).append(".*'] as dm ");sql.append("where size(dm) > 0 ");} else {sql.append("match (n:`文献`) ");}sql.append("with n ");sql.append("LIMIT ").append(limit).append(" ");sql.append("match p=(n)-[]-(k) ");sql.append("return p ");return neo4jService.run(sql.toString());}/*** 通过文献名查询文献关系** @param name 文献名* @return 文献关系*/@Overridepublic Object queryGraphByName(String name) {StringBuffer sql = new StringBuffer();sql.append("match (n:`文献`) ");if (StringUtils.isNotBlank(name)) {sql.append("where n.name='").append(name).append("' ");sql.append("return (n)-[]-() ");} else {sql.append("return (n)-[]-() ");sql.append("limit 200 ");}return neo4jService.run(sql.toString());}/*** 通过文献id查询文献知识点关系** @param id 文献id* @return 结果*/@Overridepublic NodeRelation queryKnowledgePointRelation(Long id) {StringBuffer sql = new StringBuffer();sql.append("match (p:`文献`)-[rel]-(k:`知识点`) ");sql.append(" where id(p) = ").append(id);sql.append(" return p, k, rel");List<Neo4jData> datas = neo4jService.run(sql.toString());return Neo4jNodeUtil.convert(datas);}/*** 通过节点id查询相关的知识点/文献节点数据** @param id 节点id* @return 结果*/@Overridepublic NodeRelation queryLiteratureOrKnowledgePointRelation(Long id) {StringBuffer sql = new StringBuffer();sql.append("match (p)-[rel]-(k) ");sql.append(" where id(p) = ").append(id).append(" and labels(k) in [['文献'],['知识点']] ");sql.append(" return p, k, rel");List<Neo4jData> datas = neo4jService.run(sql.toString());return Neo4jNodeUtil.convert(datas);}/*** 通过文献id查询知识词条** @param id 节点id* @return 结果*/@Overridepublic List<Neo4jNode> queryKnowledgeEntry(Long id) {StringBuffer sql = new StringBuffer();sql.append("match (p:`文献`)-[:`知识词条`]-(k) ");sql.append(" where id(p) = ").append(id);sql.append(" return k");List<Neo4jData> datas = neo4jService.run(sql.toString());return Neo4jNodeUtil.getNodes(datas);}}
import cn.hutool.core.collection.CollectionUtil;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.neo4j.driver.*;
import org.neo4j.driver.internal.InternalNode;
import org.neo4j.driver.internal.InternalPath;
import org.neo4j.driver.internal.InternalRelationship;
import org.neo4j.driver.types.Node;
import org.neo4j.driver.types.Path;
import org.neo4j.driver.types.Relationship;
import org.springframework.stereotype.Service;import java.util.*;/*** neo4j 业务接口** @author kou*/
@AllArgsConstructor
@Service
public class Neo4jServiceImpl implements INeo4jService {private final Driver driver;@Overridepublic List<Neo4jData> run(String cypherSql) {try (Session session = driver.session()) {Result result = session.run(cypherSql);return this.parseResult(result);}}/*** 开启事务执行脚本** @param cypherSql 脚本* @return 结果*/@Overridepublic List<Neo4jData> runTx(String cypherSql) {try (Session session = driver.session()) {// 开启事务try (Transaction tx = session.beginTransaction()) {Result result = tx.run(cypherSql);List<Neo4jData> dataList = this.parseResult(result);// 提交事务tx.commit();return dataList;}}}/*** 开启事务执行脚本** @param cypherSql  脚本* @param parameters 参数* @return 结果*/@Overridepublic List<Neo4jData> runTx(String cypherSql, Map<String, Object> parameters) {try (Session session = driver.session()) {// 开启事务try (Transaction tx = session.beginTransaction()) {Result result = tx.run(cypherSql, parameters);List<Neo4jData> dataList = this.parseResult(result);// 提交事务tx.commit();return dataList;}}}/*** 开启事务执行脚本** @param tx        事务* @param cypherSql 脚本* @return 结果*/@Overridepublic List<Neo4jData> runTx(Transaction tx, String cypherSql) {// 开启事务Result result = tx.run(cypherSql);return this.parseResult(result);}/*** 开启事务执行脚本** @param tx         事务* @param cypherSql  脚本* @param parameters 参数* @return 结果*/@Overridepublic List<Neo4jData> runTx(Transaction tx, String cypherSql, Map<String, Object> parameters) {// 开启事务Result result = tx.run(cypherSql, parameters);return this.parseResult(result);}/*** 批量创建节点** @param label        节点类型* @param nodeDataList 参数,{"name": "", "properties": Map<String, Object>}, label:标签类型,name:节点名称,properties: 节点数据* @return 结果*/@Overridepublic List<Neo4jData> batchCreateNode(String label, List<Map<String, Object>> nodeDataList) {// 数据不为空进行入图库Map<String, Object> parameters = new HashMap<>(1);parameters.put("props", nodeDataList);// sql格式:UNWIND $props AS p create/merge(n:Person{name: p.name} set n += p.properties)String cypherSql = "UNWIND $props AS p merge(n:" + label + "{name: p.name}) set n += p.properties";return this.runTx(cypherSql, parameters);}/*** 批量创建节点** @param tx           事务* @param label        节点类型* @param nodeDataList 参数,{"name": "", "properties": Map<String, Object>}, label:标签类型,name:节点名称,properties: 节点数据* @return 结果*/@Overridepublic List<Neo4jData> batchCreateNode(Transaction tx, String label, List<Map<String, Object>> nodeDataList) {// 数据不为空进行入图库Map<String, Object> parameters = new HashMap<>(1);parameters.put("props", nodeDataList);// sql格式:UNWIND $props AS p create/merge(n:Person{name: p.name} set n += p.properties)String cypherSql = "UNWIND $props AS p merge(n:" + label + "{name: p.name}) set n += p.properties";return this.runTx(tx, cypherSql, parameters);}/*** 批量创建节点** @param tx           事务* @param labels       节点类型* @param nodeDataList 参数,{"name": "", "properties": Map<String, Object>}, label:标签类型,name:节点名称,properties: 节点数据* @return 结果*/@Overridepublic List<Neo4jData> batchCreateNode(Transaction tx, List<String> labels, List<Map<String, Object>> nodeDataList) {// 数据不为空进行入图库Map<String, Object> parameters = new HashMap<>(1);parameters.put("props", nodeDataList);// sql格式:UNWIND $props AS p create/merge(n:Person:Country{name: p.name} set n += p.properties)StringBuffer multipleLabels = new StringBuffer();for (int i = 0; i < labels.size(); i++) {if (StringUtils.isNotBlank(labels.get(i))) {multipleLabels.append(":").append(labels.get(i));}}String cypherSql = "UNWIND $props AS p merge(n" + multipleLabels + "{name: p.name}) set n += p.properties";return this.runTx(tx, cypherSql, parameters);}/*** 批量创建关系** @param headLabel    头节点类型* @param tailLabel    尾节点类型* @param relation     关系* @param relationList 参数,{"head": "", tail:"", "properties": Map<String, Object>}, head:头节点名称,tail:尾节点名称,properties: 关系数据,必须有,可以写{}* @return 结果*/@Overridepublic List<Neo4jData> batchCreateRelationship(String headLabel, String tailLabel, String relation, List<Map<String, Object>> relationList) {Map<String, Object> parameters = new HashMap<>(1);parameters.put("props", relationList);// sql格式:UNWIND $props AS p match (n:文献{name: p.head}), (m:作者{name: p.tail}) create (n)-[r:连接]->(m)  SET r += p.propertiesString relationSql = "UNWIND $props AS p match (n: " + headLabel + "{name: p.head}), (m: " + tailLabel + "{name: p.tail}) MERGE (n)-[r:" + relation + "]->(m) SET r += p.properties";return this.runTx(relationSql, parameters);}/*** 批量创建关系** @param tx           事务* @param headLabel    头节点类型* @param tailLabel    尾节点类型* @param relation     关系* @param relationList 参数,{"head": "", tail:"", "properties": Map<String, Object>}, head:头节点名称,tail:尾节点名称,properties: 关系数据,必须有,可以写{}* @return 结果*/@Overridepublic List<Neo4jData> batchCreateRelationship(Transaction tx, String headLabel, String tailLabel, String relation, List<Map<String, Object>> relationList) {Map<String, Object> parameters = new HashMap<>(1);parameters.put("props", relationList);// sql格式:UNWIND $props AS p match (n:文献{name: p.head}), (m:作者{name: p.tail}) create (n)-[r:连接]->(m)  SET r += p.propertiesString relationSql = "UNWIND $props AS p match (n: " + headLabel + "{name: p.head}), (m: " + tailLabel + "{name: p.tail}) MERGE (n)-[r:" + relation + "]->(m) SET r += p.properties";return this.runTx(tx, relationSql, parameters);}/*** 批量创建节点及关系** @param nodeRelationDataDto 节点关系数据* @return 结果*/@Overridepublic boolean createNodeAndRelation(NodeRelationDataDto nodeRelationDataDto) {try (Session session = driver.session()) {// 开启事务try (Transaction tx = session.beginTransaction()) {// 创建节点if (CollectionUtil.isNotEmpty(nodeRelationDataDto.getNodes())) {nodeRelationDataDto.getNodes().stream().forEach(d -> {this.batchCreateNode(tx, d.getLabels(), d.getProperties());});}// 创建关系if (CollectionUtil.isNotEmpty(nodeRelationDataDto.getRelations())) {nodeRelationDataDto.getRelations().stream().forEach(r -> {this.batchCreateRelationship(tx, r.getHeadLabel(), r.getTailLabel(), r.getRelation(), r.getProperties());});}// 提交事务tx.commit();return true;}}}/*** 解析结果数据** @param result 执行结果* @return 解析结果*/private List<Neo4jData> parseResult(Result result) {List<Neo4jData> dataList = new ArrayList<>();while (result.hasNext()) {dataList.add(parseRecord(result.next()));}return dataList;}/*** 解析结果数据** @param record 执行结果* @return 解析结果*/private Neo4jData parseRecord(Record record) {Neo4jData data = new Neo4jData();data.setKeys(record.keys());Map<String, Integer> keysIndex = new HashMap<>(record.keys().size());data.setLength(record.values().size());// 字段信息List fields = new ArrayList(data.getLength());for (Map.Entry<String, Object> item : record.asMap().entrySet()) {keysIndex.put(item.getKey(), record.index(item.getKey()));if (item.getValue() instanceof InternalNode) {// 节点fields.add(this.parseNode((InternalNode) item.getValue()));} else if (item.getValue() instanceof InternalRelationship) {// 关系, 如: MATCH (n)-[rel:`作者`]->(r) return relfields.add(this.parseRelationship((InternalRelationship) item.getValue()));} else if (item.getValue() instanceof InternalPath) {// 路径, 如: MATCH p=()-[r:`作者`]->() RETURN p LIMIT 25InternalPath internalPath = (InternalPath) item.getValue();Iterator<Node> iterNode = internalPath.nodes().iterator();int count = 0;while (iterNode.hasNext()) {iterNode.next();count++;}// 当前节点数据Map<String, Object> path = new HashMap<>();// 获取节点List<Neo4jNode> nodeList = new ArrayList<>(count);Iterator<Node> nodes = internalPath.nodes().iterator();while (nodes.hasNext()) {nodeList.add(this.parseNode(nodes.next()));}if (CollectionUtil.isNotEmpty(nodeList)) {path.put("start", nodeList.get(0));if (nodeList.size() > 1) {path.put("end", nodeList.get(1));}}// 获取segmentList<Neo4jSegment> segmentsList = new ArrayList<>(count);Iterator<Path.Segment> segments = internalPath.iterator();while (segments.hasNext()) {segmentsList.add(this.parseSegment(segments.next()));}path.put("segments", segmentsList);fields.add(path);} else if (item.getValue() instanceof List) {if (CollectionUtil.isNotEmpty((Collection<?>) item.getValue())) {if (((List<?>) item.getValue()).get(0) instanceof InternalNode) {// 节点列表fields.add(this.parseNodeList((List<InternalNode>) item.getValue()));} else if (((List<?>) item.getValue()).get(0) instanceof InternalRelationship) {// 关系列表fields.add(this.parseRelationship((List<InternalRelationship>) item.getValue()));} else if (((List<?>) item.getValue()).get(0) instanceof InternalPath) {// 路径List<InternalPath> internalPathList = ((List<InternalPath>) item.getValue());Iterator<InternalPath> ipNode = internalPathList.iterator();InternalPath ipath = null;while (ipNode.hasNext()) {ipath = ipNode.next();Iterator<Node> iterNode = ipath.nodes().iterator();int count = 0;while (iterNode.hasNext()) {iterNode.next();count++;}// 当前节点数据Map<String, Object> path = new HashMap<>();// 获取节点List<Neo4jNode> nodeList = new ArrayList<>(count);Iterator<Node> nodes = ipath.nodes().iterator();while (nodes.hasNext()) {nodeList.add(this.parseNode(nodes.next()));}if (CollectionUtil.isNotEmpty(nodeList)) {path.put("start", nodeList.get(0));if (nodeList.size() > 1) {path.put("end", nodeList.get(1));}}// 获取segmentList<Neo4jSegment> segmentsList = new ArrayList<>(count);Iterator<Path.Segment> segments = ipath.iterator();while (segments.hasNext()) {segmentsList.add(this.parseSegment(segments.next()));}path.put("segments", segmentsList);fields.add(path);}}}}}data.setFieldLookup(keysIndex);data.setFields(fields);return data;}/*** 解析节点* 不解析直接返回拿不到数据** @param nodeList 节点* @return 节点*/private List<Neo4jNode> parseNodeList(List<InternalNode> nodeList) {List<Neo4jNode> dataList = new ArrayList<>(nodeList.size());nodeList.stream().forEach(n -> {dataList.add(this.parseNode(n));});return dataList;}/*** 解析节点* 不解析直接返回拿不到数据** @param node 节点* @return 节点*/private Neo4jNode parseNode(Node node) {Neo4jNode neo4jNode = new Neo4jNode();neo4jNode.setElementId(node.id());neo4jNode.setLabels(CollectionUtil.toCollection(node.labels()));neo4jNode.setProperties(node.asMap());neo4jNode.setIdentity(new Neo4jIdentity(node.id(), 0L));return neo4jNode;}/*** 解析节点* 不解析直接返回拿不到数据** @param ir 节点* @return 节点*/private Neo4jNode parseNode(InternalNode ir) {Neo4jNode node = new Neo4jNode();node.setElementId(ir.id());node.setLabels(ir.labels());node.setProperties(ir.asMap());node.setIdentity(new Neo4jIdentity(ir.id(), 0L));return node;}/*** 解析关系* 不解析直接返回拿不到数据** @param relList 关系列表* @return 关系*/private List<Neo4jRelation> parseRelationship(List<InternalRelationship> relList) {List<Neo4jRelation> dataList = new ArrayList<>(relList.size());relList.stream().forEach(n -> {dataList.add(this.parseRelationship(n));});return dataList;}/*** 解析关系* 不解析直接返回拿不到数据** @param rel 关系* @return 关系*/private Neo4jRelation parseRelationship(InternalRelationship rel) {Neo4jRelation relation = new Neo4jRelation();relation.setElementId(rel.id());relation.setStartNodeElementId(rel.startNodeId());relation.setEndNodeElementId(rel.endNodeId());relation.setType(rel.type());relation.setProperties(rel.asMap());relation.setIdentity(new Neo4jIdentity(rel.id(), 0L));relation.setStart(new Neo4jIdentity(rel.startNodeId(), 0L));relation.setEnd(new Neo4jIdentity(rel.endNodeId(), 0L));return relation;}/*** 解析关系* 不解析直接返回拿不到数据** @param rel 关系* @return 关系*/private Neo4jRelationship parseRelationship(Relationship rel) {Neo4jRelationship relation = new Neo4jRelationship();relation.setElementId(rel.id());relation.setStartNodeElementId(rel.startNodeId());relation.setEndNodeElementId(rel.endNodeId());relation.setIdentity(new Neo4jIdentity(rel.id(), 0L));relation.setStart(new Neo4jIdentity(rel.startNodeId(), 0L));relation.setEnd(new Neo4jIdentity(rel.endNodeId(), 0L));relation.setType(rel.type());relation.setProperties(rel.asMap());return relation;}/*** 解析关系* 不解析直接返回拿不到数据** @param segment* @return 关系*/private Neo4jSegment parseSegment(Path.Segment segment) {Neo4jSegment seg = new Neo4jSegment();seg.setStart(this.parseNode(segment.start()));seg.setEnd(this.parseNode(segment.end()));seg.setRelationship(this.parseRelationship(segment.relationship()));return seg;}
}
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;import java.util.List;
import java.util.Map;/*** neo4j执行cypher语句返回结果** @author kou*/
@Data
public class Neo4jData {/*** 查询字段*/private List<String> keys;/*** 长度,fields个数*/private Integer length;/*** 数据字段*/@JsonProperty(value = "_fields")private List fields;/*** keys索引,字段keys在fields的位置*/@JsonProperty(value = "_fieldLookup")private Map<String, Integer> fieldLookup;}
import lombok.Data;import java.util.Collection;
import java.util.Map;/*** 结点信息** @author kou*/
@Data
public class Neo4jNode {/*** 结点id*/private Long elementId;private Neo4jIdentity identity;/*** label名称*/private Collection<String> labels;/*** 属性*/private Map<String, Object> properties;}
import lombok.Data;import java.util.Map;/*** neo4j关系** @author kou*/
@Data
public class Neo4jRelation {/*** 关系id*/private Long elementId;/*** 关系类型*/private String type;/*** id信息*/private Neo4jIdentity identity;/*** 头节点信息*/private Neo4jIdentity start;/*** 尾节点信息*/private Neo4jIdentity end;/*** 头节点id*/private Long startNodeElementId;/*** 尾节点id*/private Long endNodeElementId;/*** 属性*/private Map<String, Object> properties;}
import cn.hutool.core.collection.CollectionUtil;import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** cypher脚本结果工具类** @author kou*/
public class Neo4jNodeUtil {/*** 将cypher脚本查询出的结果转换为节点关系** @param datas cypher脚本查询出的结果* @return 节点关系*/public static NodeRelation convert(List<Neo4jData> datas) {if (CollectionUtil.isEmpty(datas)) {return null;}int length = datas.size() * 3;List<Neo4jNode> nodes = new ArrayList<>(length);List<Neo4jRelation> relations = new ArrayList<>(length);Map<Long, Long> nodeIds = new HashMap<>(length);Map<Long, Long> relationIds = new HashMap<>(length);datas.stream().forEach(d -> {d.getFields().stream().forEach(f -> {if (f instanceof Neo4jNode) {Neo4jNode node = (Neo4jNode) f;if (null == nodeIds.get(node.getElementId())) {nodeIds.put(node.getElementId(), node.getElementId());Map<String, Object> properties = node.getProperties();if (CollectionUtil.isNotEmpty(properties) && properties.containsKey("embedding")) {properties = ImmutableMap.copyOf(Maps.filterKeys(properties, key -> !key.equals("embedding")));node.setProperties(properties);}nodes.add(node);}} else if (f instanceof Neo4jRelation) {Neo4jRelation rel = (Neo4jRelation) f;if (null == relationIds.get(rel.getElementId())) {relationIds.put(rel.getElementId(), rel.getElementId());relations.add(rel);}}});});NodeRelation nodeRelation = new NodeRelation();nodeRelation.setNodes(nodes);nodeRelation.setRelations(relations);return nodeRelation;}/*** 获取节点** @param datas cypher脚本查询出的结果* @return 节点关系*/public static List<Neo4jNode> getNodes(List<Neo4jData> datas) {if (CollectionUtil.isEmpty(datas)) {return null;}List<Neo4jNode> nodes = new ArrayList<>(datas.size());Map<Long, Long> nodeIds = new HashMap<>(datas.size());datas.stream().forEach(d -> {d.getFields().stream().forEach(f -> {if (f instanceof Neo4jNode) {Neo4jNode node = (Neo4jNode) f;if (null == nodeIds.get(node.getElementId())) {nodeIds.put(node.getElementId(), node.getElementId());Map<String, Object> properties = node.getProperties();if (CollectionUtil.isNotEmpty(properties) && properties.containsKey("embedding")) {properties = ImmutableMap.copyOf(Maps.filterKeys(properties, key -> !key.equals("embedding")));node.setProperties(properties);}nodes.add(node);}}});});return nodes;}}

使用jpa进行查询

    /*** 文献搜索** @param keyword  关键字* @param pageable 分页查询* @return 结果*/@Overridepublic Page<Literature> search(String keyword, Pageable pageable) {ExampleMatcher matcher = ExampleMatcher.matching().withMatcher("name", match -> match.contains()).withMatcher("fullPaperOutlineEn", match -> match.contains()).withMatcher("fullPaperOutlineZh", match -> match.contains()).withMatcher("fullPaperSummaryEn", match -> match.contains()).withMatcher("fullPaperSummaryZh", match -> match.contains());Literature literature = new Literature();literature.setName(keyword);literature.setFullPaperOutlineEn(keyword);literature.setFullPaperOutlineZh(keyword);literature.setFullPaperSummaryEn(keyword);literature.setFullPaperSummaryZh(keyword);// return literatureRepository.findByNameLike(keyword, pageable);return literatureRepository.findAll(Example.of(literature, matcher), pageable);}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/757853.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

首页效果炫酷的wordpress免费主题模板

视频背景免费WP主题 简洁大气的视频背景wordpress主题&#xff0c;找大视频背景的主题可以看看这个。 https://www.wpniu.com/themes/193.html 红色全屏大图WP主题 非常经典的一款免费wordpress主题&#xff0c;红色全屏大图满足多行业使用。 https://www.wpniu.com/themes…

贴片电感的工艺结构原理及选型参数总结

🏡《总目录》 目录 1,概述2,工作原理3,结构特点3.1,耐电流叠加特性3.2,耐冲击噪音低3.3,全屏蔽结构绿色环保性好3.4,损耗低、耐热性好3.5,作业频带宽4,工艺流程4.1,线圈绕制4.2,磁芯制作4.3,导线制作4.4,封装

蓝桥杯算法基础(11):十大排序算法(冒泡排序)c语言般版

十大排序算法合集&#xff08;c语言般&#xff09; 冒泡排序 选择排序 插入排序 希尔排序 快速排序 归并排序 堆排序 计数排序 桶排序 基数排序 分类: 交换类 1.冒泡排序 2.快速排序 分配类 1.计数排序 2.基数排序 选择类 1.选择排序 归并类 1.归并排序 插入类 1.插入…

9.登入页面

登入页面 在pages中新建页面login 修改代码 <template><view></view> </template><script setup></script><style lang"scss"></style>添加头像组件 官网 https://vkuviewdoc.fsq.pub/components/avatar.html …

Oracle中使用coe_load_sql_profile脚本固定执行计划

coe_load_sql_profile.sql 是Oracle数据库环境下用于迁移或固定SQL执行计划的一个脚本&#xff0c;它可以帮助DBA将特定SQL语句的高效执行计划转化为SQL Profile&#xff0c;并将其应用到目标数据库中。 SQL Profile是一种Oracle数据库中用来指导优化器选择特定执行计划的方法。…

【靶机测试--PHOTOGRAPHER: 1【php提权】】

前期准备 靶机下载地址&#xff1a; https://vulnhub.com/entry/photographer-1%2C519/ 信息收集 nmap 扫描同网段 ┌──(root㉿kali)-[/home/test/桌面] └─# nmap -sP 192.168.47.0/24 --min-rate 3333 Starting Nmap 7.92 ( https://nmap.org ) at 2024-03-19 07:37 …

SpringCloud Alibaba Nacos 服务注册和配置中心

一、前言 接下来是开展一系列的 SpringCloud 的学习之旅&#xff0c;从传统的模块之间调用&#xff0c;一步步的升级为 SpringCloud 模块之间的调用&#xff0c;此篇文章为第十二篇&#xff0c;即介绍 SpringCloud Alibaba Nacos 服务注册和配置中心。 二、Nacos 简介 2.1 为…

SpringBoot 监控 SQL 运行情况

Druid 数据库连接池相信很多小伙伴都用过,个人感觉 Druid 是阿里比较成功的开源项目了,不像 Fastjson 那么多槽点,Druid 各方面一直都比较出色,功能齐全,使用也方便,基本的用法就不说了,今天我们来看看 Druid 中的监控功能。 准备工作 首先我们来创建一个 Spring Boot…

Android API 30及更高版本网络权限设置

目录 一、网络权限设置二、配置步骤1、在 AndroidManifest.xml 文件中添加网络权限声明2、在 AndroidManifest.xml 文件中的 application 节点下配置网络安全策略 一、网络权限设置 在 Android API 30 及更高版本中&#xff0c;Google 引入了更严格的网络安全策略&#xff0c;…

wireshark数据捕获实验简述

Wireshark是一款开源的网络协议分析工具&#xff0c;它可以用于捕获和分析网络数据包。是一款很受欢迎的“网络显微镜”。 实验拓扑图&#xff1a; 实验基础配置&#xff1a; 服务器&#xff1a; ip:172.16.1.88 mask:255.255.255.0 r1: sys sysname r1 undo info enable in…

YOLOv5目标检测学习(6):源码解析之:训练部分train.py

文章目录 前言一、导入相关包与配置二、主函数main2.1 checks&#xff1a;检查rank值来判断是否打印参数、检查git仓库、检查包的安装2.2 判断是否恢复上一次模型训练提问&#xff1a;opt.data, opt.cfg, opt.hyp, opt.weights, opt.project各是什么&#xff1f; 2.3 DDP mode&…

【数据结构】哈希表与哈希桶

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》《Linux》《算法》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负 目录 前言 1.概念 2.哈希冲突…

mysql查询条件包含IS NULL、IS NOT NULL、!=、like %* 、like %*%,不能使用索引查询,只能使用全表扫描,是真的吗???

不知道是啥原因也不知道啥时候, 江湖上流传着这么一个说法 mysql查询条件包含IS NULL、IS NOT NULL、!、like %* 、like %*%,不能使用索引查询&#xff0c;只能使用全表扫描。 刚入行时我也是这么认为的&#xff0c;还奉为真理&#xff01; 但是时间工作中你会发现还是走索引…

Linux 常用运维使用指令

查询占用 CPU 最高的前 10 个进程 ps aux|grep -v PID|sort -rn -k 3|head 查询占用内存最大的前 10 个进程 ps aux|grep -v PID|sort -rn -k 4|head Linux du 获取文件比较大的前十 du -h / | sort -rh | head -n 10 解释&#xff1a; du: 磁盘使用情况命令。 -h: 参数…

C++基础入门(命名空间,函数,引用)

文章目录 前言1,命名空间2,函数函数重载缺省参数内联函数 3,引用尾声 前言 欢迎来到这篇关于C的入门博客&#xff01;C是一门强大而又广泛应用的编程语言&#xff0c;作为一门面向对象的编程语言&#xff0c;C可以让你更好地组织和管理代码&#xff0c;提高代码的重用性和可维…

带你学会深度学习之卷积神经网络[CNN] - 3

前言 本文不讲述如泛化&#xff0c;前向后向传播&#xff0c;过拟合等基础概念。 本文图片来源于网络&#xff0c;图片所有者可以随时联系笔者删除。 CNN&#xff0c;常用于计算机视觉&#xff0c;是计算机视觉方面常见的基础模型&#xff0c;后面发展的有很多其他变种&…

实验7-3-6 字符串转换成十进制整数(PTA)

题目&#xff1a; 输入一个以#结束的字符串&#xff0c;本题要求滤去所有的非十六进制字符&#xff08;不分大小写&#xff09;&#xff0c;组成一个新的表示十六进制数字的字符串&#xff0c;然后将其转换为十进制数后输出。如果在第一个十六进制字符之前存在字符“-”&#…

图书推荐|图解算法:C语言实现+视频教学版

零负担理解数据结构及其算法的设计&#xff0c;零基础也能快速上手编程。 本书内容 《图解算法&#xff1a;C语言实现视频教学版》是一本综合讲述数据结构及其算法的入门书&#xff0c;力求简洁、清晰、严谨、且易于学习和掌握。 《图解算法&#xff1a;C语言实现视频教学版》…

Java基础学习: http请求中ContentType类型的取值

HTTP请求中的Content-Type头部用于指示发送到服务器的数据或从服务器发送到客户端的数据的媒体类型。以下是一些常见的Content-Type类型&#xff1a; application/json 用于发送或接收JSON格式的数据。JSON是一种轻量级的数据交换格式&#xff0c;易于人阅读和编写&#xff0c;…

经过拦截器cookie验证后用户信息放入哪里,以便后面接口使用

1.基于ThreadLocal实现&#xff0c;拦截器获取的用户信息在接口中使用_threadloacl获取账号数据_JAVA&#xff24;WangJing的博客-CSDN博客2基于ThreadLocal实现&#xff0c;拦截器获取的用户信息在接口中使用_threadloacl获取账号数据https://blog.csdn.net/wang_jing_jing/ar…