Neo4j(CQL)学习记录-06(Cypher Query Language)

这篇文章将主要记录通过java来链接Neo4j数据库进行简单,复杂查询的api编写

查询指定标签的节点,以及指定属性

MATCH (n:label {property: $propertyValue}) RETURN n;按照这个CQL来组装动态参数,实现如下:

    /**
     * 功能描述:查询指定标签的节点,以及指定属性
     *
     * @param label      标签
     * @param properties 属性
     * @return {@link List }<{@link Object }>
     * @author zhongzy
     * @date 2024/05/17
     */

    public List<Object> searchNode(String label, Map<String, Object> properties) {
        try (Session session = driver.session()) {
            StringBuilder sb = new StringBuilder("MATCH (n:" + label);
            appendProperties(sb,"n",properties);
            sb.append(") RETURN n");
            return session.run(sb.toString(), Values.value(properties)).list().stream().map(record -> record.get("n").asMap()).collect(toList());
        }
    }

查询所有节点,限制个数

MATCH (n) RETURN n LIMIT $limit;按照这个CQL来组装动态参数,实现如下:

    /**
     * 功能描述:查询所有节点,限制个数
     *
     * @param limit 限制
     * @return {@link List }<{@link Object }>
     * @author zhongzy
     * @date 2024/05/17
     */
    public List<Object> searchNode(int limit){
       try(Session session = driver.session()){
            return session.run("MATCH (n) RETURN n LIMIT $limit",parameters("limit",limit)).list().stream().map(record -> record.get("n").asMap()).collect(toList());
       }
    }

查询所有关系

MATCH ()-[r]->() RETURN r;按照这个CQL来组装动态参数,实现如下:

 /**
     * 功能描述:查询所有关系
     *
     * @return {@link List }<{@link Object }>
     * @author zhongzy
     * @date 2024/05/17
     */

    public List<Object> searchRelationShip(){
        try(Session session = driver.session()){
            return session.run("MATCH ()-[r]->() RETURN r").list().stream().map(record -> record.get("r").asMap()).collect(toList());
        }
    }

查询指定关系

MATCH (a:person {name: "沙僧"})-[r]-(b:person {name: "猪八戒"}) RETURN r;按照这个CQL来组装动态参数,实现如下:

 /**
     * 功能描述:查询指定关系
     *
     * @param fromLabel              起始节点
     * @param fromProperties         起始节点属性
     * @param toLabel                目标节点
     * @param toProperties           目标节点属性
     * @param relationshipType       关系类型
     * @param relationshipProperties 关系属性
     * @return {@link List }<{@link Object }>
     * @author zhongzy
     * @date 2024/05/17
     */

    public List<Object> searchRelationShip(String fromLabel, Map<String, Object> fromProperties, String toLabel, Map<String, Object> toProperties, String relationshipType, Map<String, Object> relationshipProperties){
        try(Session session = driver.session()){
            StringBuilder sb = new StringBuilder("MATCH (a:" + fromLabel);
            appendProperties(sb, "a", fromProperties);
            sb.append(") MATCH (b:" + toLabel);
            appendProperties(sb, "b", toProperties);
            sb.append(") MATCH (a)-[r:" + relationshipType);
            appendProperties(sb, "r", relationshipProperties);
            sb.append("]->(b) RETURN r");
            Map<String, Object> parameters = new HashMap<>();
            addPropertiesToParameters(parameters, addPrefixToProperties(fromProperties, "a_"));
            addPropertiesToParameters(parameters, addPrefixToProperties(toProperties, "b_"));
            addPropertiesToParameters(parameters, addPrefixToProperties(relationshipProperties, "r_"));
            return session.run(sb.toString(), Values.value(parameters)).list().stream().map(record -> record.get("r").asMap()).collect(toList());
        }
    }

查询指定节点的属性已经关系还有对应节点值

MATCH (a:person {name: "沙僧"})-[r]-(b:person {name: "猪八戒"}) RETURN a,r,b;按照这个CQL来组装动态参数,这里的查询我将给出自己封装的响应类和封装方法,实现如下:

NodeResult实体类,接收节点数据封装

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.neo4j.driver.types.Node;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Zhongzy
 * @description
 * @since 2024-05-17 15:52
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class NodeResult {
    private List<String> labels;
    private Map<String, Object> properties;
    private String elementId;

    public void copyNode(Node a){ //复制响应中的元素,封装为想要的响应结果
        this.setLabels((List<String>) a.labels());
        this.setElementId(a.elementId());
        Map<String, Object> nodeAMap = new HashMap<>();
        a.keys().forEach(k -> {
            nodeAMap.put(k, a.get(k));
        });
        this.setProperties(nodeAMap);
    }
}

RelationshipResult关系实体类,返回关系响应体

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.neo4j.driver.types.Relationship;

import java.util.HashMap;
import java.util.Map;

/**
 * @author Zhongzy
 * @description
 * @since 2024-05-17 15:59
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class RelationshipResult {
    private String type;
    private Map<String, Object> properties;
    private String elementId;
    private String startElementId;
    private String endElementId;

    public void copyFromRelationship(Relationship r) { //封装响应体
        Map<String, Object> relationMap = new HashMap<>();
        r.keys().forEach(k -> {
            relationMap.put(k, r.get(k));
        });
        this.properties = relationMap;
        this.elementId = r.elementId();
        this.type = r.type();
        this.endElementId = r.endNodeElementId();
        this.startElementId = r.startNodeElementId();

    }
}

ResponseResult节点关系响应体

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Map;

/**
 * @author Zhongzy
 * @description
 * @since 2024-05-17 15:27
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ResponseResult {
    private Map<String, Object> nodeA;
    private Map<String, Object> relationship;
    private Map<String, Object> nodeB;
}

searchNodeAndRelationship实现方法

查询指定的节点和关系 MATCH  (a:person {name: "沙僧"})-[r]-(b:person {name: "猪八戒"}) RETURN a,r,b

    /**
     * 功能描述:查询指定的节点和关系 MATCH  (a:person {name: "沙僧"})-[r]-(b:person {name: "猪八戒"}) RETURN a,r,b
     *
     * @param fromLabel        从标签
     * @param fromNodeProperty From Node 属性
     * @param toLabel          到标签
     * @param toNodeProperty   To Node 属性
     * @param type             类型
     * @param proNodeProperty  Pro Node 属性
     * @return {@link List }<{@link ResponseResult }>
     * @author zhongzy
     * @date 2024/05/20
     */

    public List<ResponseResult> searchNodeAndRelationship(String fromLabel, Map<String, Object> fromNodeProperty, String toLabel, Map<String, Object> toNodeProperty, String type, Map<String, Object> proNodeProperty) {
        try (Session session = driver.session()) {
            StringBuilder sb = new StringBuilder("MATCH (a:" + fromLabel);
            appendProperties(sb, "a", fromNodeProperty);
            sb.append(") MATCH (b:" + toLabel);
            appendProperties(sb, "b", toNodeProperty);
            sb.append(") MATCH (a)-[r:" + type);
            appendProperties(sb, "r", proNodeProperty);
            sb.append("]->(b) RETURN a,b,r");
            Map<String, Object> parameters = new HashMap<>();
            addPropertiesToParameters(parameters, addPrefixToProperties(fromNodeProperty, "a_"));
            addPropertiesToParameters(parameters, addPrefixToProperties(toNodeProperty, "b_"));
            addPropertiesToParameters(parameters, addPrefixToProperties(proNodeProperty, "r_"));
            Result result = session.run(sb.toString(), Values.value(parameters));

            List<ResponseResult> responseResult = new ArrayList<>();

            while (result.hasNext()) {
                //启动node
                NodeResult fromNode = new NodeResult();
                //目标node
                RelationshipResult relation = new RelationshipResult();
                //关系
                NodeResult toNode = new NodeResult();
                //获取关系
                Record record = result.next();
                encapsulation(fromNode, relation, toNode, record, responseResult);
            }
            return responseResult;
        }
    }

    /**
     * 功能描述:封装
     *
     * @param fromNode       从节点
     * @param relation       关系
     * @param toNode         到节点
     * @param record         记录
     * @param responseResult
     * @author zhongzy
     * @date 2024/05/20
     */

    private void encapsulation(NodeResult fromNode, RelationshipResult relation, NodeResult toNode, Record record, List<ResponseResult> responseResult) {
        ResponseResult result = new ResponseResult();
        Node a = record.get("a").asNode();
        //设置节点值
        fromNode.copyNode(a);
        //设置属性
        Relationship r = record.get("r").asRelationship();
        relation.copyFromRelationship(r);

        Node b = record.get("b").asNode();
        toNode.copyNode(b);

        Map<String, Object> nodeA = new HashMap<>();
        nodeA.put("a", fromNode);
        Map<String, Object> relationR = new HashMap<>();
        relationR.put("r", relation);
        Map<String, Object> nodeB = new HashMap<>();
        nodeB.put("b", toNode);
        result.setNodeA(nodeA);
        result.setNodeB(nodeB);
        result.setRelationship(relationR);

        responseResult.add(result);
    }

这里给出返回的响应体结构是这样的,返回了在neo4j-desktop中展示出来的同款响应体,效果达成。

[ResponseResult(nodeA = {
	a = NodeResult(labels = [person], properties = {
		name = "唐僧"
	},
	elementId = 4 : 58f2796d - d800 - 4bc7 - a466 - 6f556f36fa3b: 2)
},
relationship = {
	r = RelationshipResult(type = 徒弟, properties = {
		year = "2024"
	},
	elementId = 5 : 58f2796d - d800 - 4bc7 - a466 - 6f556f36fa3b: 6, startElementId = 4 : 58f2796d - d800 - 4bc7 - a466 - 6f556f36fa3b: 2, endElementId = 4 : 58f2796d - d800 - 4bc7 - a466 - 6f556f36fa3b: 3)
},
nodeB = {
	b = NodeResult(labels = [person], properties = {
		name = "孙悟空"
	},
	elementId = 4 : 58f2796d - d800 - 4bc7 - a466 - 6f556f36fa3b: 3)
}), ResponseResult(nodeA = {
	a = NodeResult(labels = [person], properties = {
		name = "唐僧"
	},
	elementId = 4 : 58f2796d - d800 - 4bc7 - a466 - 6f556f36fa3b: 2)
},
relationship = {
	r = RelationshipResult(type = 徒弟, properties = {
		year = "2024"
	},
	elementId = 5 : 58f2796d - d800 - 4bc7 - a466 - 6f556f36fa3b: 7, startElementId = 4 : 58f2796d - d800 - 4bc7 - a466 - 6f556f36fa3b: 2, endElementId = 4 : 58f2796d - d800 - 4bc7 - a466 - 6f556f36fa3b: 4)
},
nodeB = {
	b = NodeResult(labels = [person], properties = {
		name = "猪八戒"
	},
	elementId = 4 : 58f2796d - d800 - 4bc7 - a466 - 6f556f36fa3b: 4)
}), ResponseResult(nodeA = {
	a = NodeResult(labels = [person], properties = {
		name = "唐僧"
	},
	elementId = 4 : 58f2796d - d800 - 4bc7 - a466 - 6f556f36fa3b: 2)
},
relationship = {
	r = RelationshipResult(type = 徒弟, properties = {
		year = "2024"
	},
	elementId = 5 : 58f2796d - d800 - 4bc7 - a466 - 6f556f36fa3b: 8, startElementId = 4 : 58f2796d - d800 - 4bc7 - a466 - 6f556f36fa3b: 2, endElementId = 4 : 58f2796d - d800 - 4bc7 - a466 - 6f556f36fa3b: 5)
},
nodeB = {
	b = NodeResult(labels = [person], properties = {
		name = "沙僧"
	},
	elementId = 4 : 58f2796d - d800 - 4bc7 - a466 - 6f556f36fa3b: 5)
})]

通过深度查询相关节点以及关系

    /**
     * 功能描述:MATCH path = (n)-[*..depth]->(m)
     * WHERE elementId(n) = {startNodeId}
     * RETURN path 深度遍历,查询指定节点的深度关系
     * TODO 可以添加其他参数,暂定最暴力版本
     *
     * @return
     * @author zhongzy
     * @date 2024/05/21
     */
    public List<DepthResult> searchNodeAndRelationByDepth(String elementId, int depth) {
        try (Session session = driver.session()) {
            StringBuilder sb = new StringBuilder("MATCH path = (" + N.getValue() + ")-[*..");
            sb.append(depth).append("]->(").append(M.getValue()).append(") where elementId(").append(N.getValue()).append(") = '").append(elementId).append("' return path");
            Result run = session.run(sb.toString());
            return getDepthResult(run);
        }
    }

完整代码有兴趣的可以私聊博主~持续更新中

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值