求 关于直接用数据库里node间的关系,return一段json的具体操作例子
发布于 4 年前 作者 VeraQian1225 1660 次浏览 来自 问答

大家好,Neo4j新手,想问一个问题。 我想基于现有的数据关系,做一下细则的分类在json中,最后直接用query return一段json出来,这样可行吗? 网上查了一下感觉例子不是特别的多,希望做过类似 或者了解的大佬分享一点example给我学习一下,或者给我点方向。 自己在网上看了好像是可以用到unwind, merge这样的方法。可是有点复杂不知道具体如何最后把想要的东西给return出来。 非常感谢!

4 回复

你的问题是,需要从NEO4J查询数据,然后直接返回JSON数据对吧?这样的话你可以直接使用rest api查询数据,然后根据rest api返回的数据格式,单独写一个数据封装的工具,这样你就可以直接使用java driver直接查询出json数据了。下面是一个参考:

package casia.isi.neo4j.driver;
import casia.isi.neo4j.common.CRUD;
import casia.isi.neo4j.common.TimeUnit;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.log4j.Logger;
import org.neo4j.driver.internal.value.*;
import org.neo4j.driver.v1.*;
import org.neo4j.driver.v1.types.Node;
import org.neo4j.driver.v1.types.Path;
import org.neo4j.driver.v1.types.Relationship;
import org.neo4j.driver.v1.util.Pair;
import java.util.List;
import java.util.Map;
public class Neo4jDriver {
    /**
     * JAVA_DRIVER返回的数据格式统一按照D3_GRAPH格式返回
     **/
    private final static Logger logger = org.apache.log4j.Logger.getLogger(Neo4jDriver.class);
    /**
     * @param driver:传入NEO4J_JAVA驱动
     * @param statement:cypher
     * @return
     * [@Description](/user/Description): TODO(构图导入等操作访问)
     */
    public synchronized static JSONObject composer(Driver driver, String statement) {
        long startMill = System.currentTimeMillis();
        boolean flag = false;
        // RETRY FAILURE QUERY
        while (!flag) {
            try (Session session = driver.session()) {
                try (Transaction tx = session.beginTransaction()) {
                    tx.run(statement);
                    tx.success();  // Mark this write as successful.
                    flag = true;
                }
            } catch (Exception e) {
                logger.info("Retrying query " + statement);
            }
        }
        long stopMill = System.currentTimeMillis();
        long consume = (stopMill - startMill) / Integer.parseInt(String.valueOf(TimeUnit.MILL_SECOND_CV.getSymbolValue()));
        if (consume != 0) {
            logger.info("Neo4j driver composer success!consume:" + consume + "s");
        } else {
            logger.info("Neo4j driver composer success!consume:" + (stopMill - startMill) + "mills");
        }
        return new JSONObject();
    }

    /**
     * @param driver:传入NEO4J_JAVA驱动
     * @param statement:cypher
     * @return
     * [@Description](/user/Description): TODO(构图导入等操作访问)
     */
    public synchronized static JSONObject composerReturnNodeId(Driver driver, String statement) {
        JSONObject resultMessage = new JSONObject();
        long startMill = System.currentTimeMillis();
        try (Session session = driver.session()) {
            try (Transaction tx = session.beginTransaction()) {
                StatementResult result = tx.run(statement);
                while (result.hasNext()) {
                    Record record = result.next();
                    Map<String, Object> map = record.asMap();
                    JSONObject object = JSONObject.parseObject(JSON.toJSONString(map));
                    resultMessage.putAll(object);
                }
                tx.success();  // Mark this write as successful.
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        long stopMill = System.currentTimeMillis();
        long consume = (stopMill - startMill) / Integer.parseInt(String.valueOf(TimeUnit.MILL_SECOND_CV.getSymbolValue()));
        if (consume != 0) {
            logger.info("Neo4j merge composer success!consume:" + consume + "s");
        } else {
            logger.info("Neo4j merge composer success!consume:" + (stopMill - startMill) + "mills");
        }
        return resultMessage;
    }

    /**
     * @param driver:传入NEO4J_JAVA驱动
     * @param statement:cypher
     * @return
     * [@Description](/user/Description): TODO(构图导入等操作访问)
     */
    public synchronized static JSONObject composerAutoCommit(Driver driver, String statement) {
        long startMill = System.currentTimeMillis();
        try (Session session = driver.session()) {
            /**
             * AUTO COMMIT TRANSACTION
             * **/
            session.run(statement);
        } catch (Exception e) {
            e.printStackTrace();
        }
        long stopMill = System.currentTimeMillis();
        long consume = (stopMill - startMill) / Integer.parseInt(String.valueOf(TimeUnit.MILL_SECOND_CV.getSymbolValue()));
        logger.info("Neo4j driver composer auto commit success!consume:" + consume + "s");
        return new JSONObject();
    }

    public static JSONObject rowProperties(Driver driver, String cypher) {
        JSONObject resultObject = new JSONObject();
        JSONArray resultArray = new JSONArray();
        try (Session session = driver.session()) {
            StatementResult result = session.run(cypher);
            while (result.hasNext()) {
                Record record = result.next();
                Map<String, Object> map = record.asMap();
                JSONObject object = JSONObject.parseObject(JSON.toJSONString(map));
                resultArray.add(object);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        resultObject.put(CRUD.RETRIEVE_PROPERTIES.getSymbolValue(), resultArray);
        return resultObject;
    }

    /**
     * @param driver:传入NEO4J_JAVA驱动
     * @param statement:cypher
     * @return
     * [@Description](/user/Description): TODO(检索)
     */
    public static JSONObject searcher(Driver driver, String statement) {

        long startMill = System.currentTimeMillis();

        JSONObject results = new JSONObject();
        JSONArray resultArray = new JSONArray();
        JSONObject arrayObject = new JSONObject();

        JSONArray columns = new JSONArray();
        JSONArray data = new JSONArray();
        JSONObject dataObject = new JSONObject();
        JSONObject graph = new JSONObject();

        JSONArray relationships = new JSONArray();
        JSONArray nodes = new JSONArray();
        JSONArray properties = new JSONArray();

        try (Session session = driver.session()) {
            // Auto-commit transactions are a quick and easy way to wrap a read.

            StatementResult result = session.run(statement);
            // Each Cypher execution returns a stream of records.
            while (result.hasNext()) {
                Record record = result.next();
                // Values can be extracted from a record by index or name.

                List<Pair<String, Value>> list = record.fields();

                JSONObject propertiesPack = new JSONObject();
                for (int i = 0; i < list.size(); i++) {
                    Pair<String, Value> stringValuePair = list.get(i);
                    if (!columns.contains(stringValuePair.key())) {
                        columns.add(stringValuePair.key());
                    }
                    Value value = stringValuePair.value();
                    if (value instanceof NodeValue) {
                        JSONObject objectNode = packNode(value.asNode());
                        if (!nodes.contains(objectNode)) nodes.add(objectNode);
                    } else if (value instanceof PathValue) {

                        JSONArray objectNodes = packNodeByPath(value.asPath());
                        objectNodes.forEach(node -> {
                            JSONObject nodeObj = (JSONObject) node;
                            if (!nodes.contains(nodeObj)) nodes.add(nodeObj);
                        });

                        JSONArray objectRelas = packRelations(value.asPath());
                        objectRelas.forEach(relation -> {
                            JSONObject relationObj = (JSONObject) relation;
                            if (!relationships.contains(relationObj)) relationships.add(relationObj);
                        });
                    } else {
                        propertiesPack.putAll(packStringValuePair(stringValuePair));
                    }
                }
                if (!propertiesPack.isEmpty()) properties.add(propertiesPack);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        graph.put("relationships", relationships);
        graph.put("nodes", nodes);
        graph.put("properties", properties);
        dataObject.put("graph", graph);
        data.add(dataObject);
        arrayObject.put("data", data);
        arrayObject.put("columns", columns);
        resultArray.add(arrayObject);
        results.put("results", resultArray);
        results.put("totalNodeSize", nodes.size());
        results.put("totalRelationSize", relationships.size());

        long stopMill = System.currentTimeMillis();
        long consume = (stopMill - startMill) / Integer.parseInt(String.valueOf(TimeUnit.MILL_SECOND_CV.getSymbolValue()));
        logger.info("Neo4j driver searcher success!consume:" + consume + "s");
        return results;
    }

    private static JSONObject packStringValuePair(Pair<String, Value> stringValuePair) {
        String key = stringValuePair.key();
        Value value = stringValuePair.value();
        JSONObject object = new JSONObject();
        if (value instanceof BooleanValue) {
            object.put(key, value.asBoolean());
        } else if (value instanceof FloatValue) {
            object.put(key, value.asFloat());
        } else if (value instanceof IntegerValue) {
            // object.put(key, value.asInt());
            object.put(key, value.asLong());
        } else if (value instanceof ListValue) {
            object.put(key, value.asList());
        } else {
            object.put(key, value.asString());
        }
        return object;
    }

    private static JSONArray packRelations(Path path) {
        JSONArray arrayRelations = new JSONArray();
        for (Relationship relationship : path.relationships()) {
            arrayRelations.add(packRelation(relationship));
        }
        return arrayRelations;
    }

    private static JSONObject packRelation(Relationship relationship) {
        JSONObject currentRelation = new JSONObject();
        currentRelation.put("startNode", relationship.startNodeId());
        currentRelation.put("id", relationship.id());
        currentRelation.put("type", relationship.type());
        currentRelation.put("endNode", relationship.endNodeId());
        currentRelation.put("properties", JSONObject.parseObject(JSON.toJSONString(relationship.asMap())));
        return currentRelation;
    }

    private static JSONArray packNodeByPath(Path path) {
        JSONArray pathNodes = new JSONArray();
        for (Node node : path.nodes()) {
            pathNodes.add(packNode(node));
        }
        return pathNodes;
    }

    private static JSONObject packNode(Node node) {
        JSONObject currentNode = new JSONObject();
        currentNode.put("id", node.id());
        currentNode.put("properties", JSONObject.parseObject(JSON.toJSONString(node.asMap())));
        currentNode.put("labels", JSONArray.parseArray(JSON.toJSONString(node.labels())));
        return currentNode;
    }
}

Thank you, @crazyyanchao 哇 这个感觉有点复杂。。我就是想写段query,直接可以拿到我想要的json,请问还有简单点的方法吗?谢谢你

下面这些是JSON的生成方式,你可以试试,不知道满不满足你的需求:)

// 1、数据导出为JSON文件,生成的JSON在neo4j安装目录下的import目录下:
CALL apoc.export.json.query('match (n) return n limit 10','test.json')
// 2、将整个库导出到指定的JSON文件
CALL apoc.export.json.all('all.json',null)
// 3、将指定的节点和关系导出到指定的JSON文件
MATCH (nod)
MATCH ()-[reels]->() 
 WITH collect(nod) as node, collect(reels) as rels
CALL apoc.export.json.data(node, rels, {file}, null) 
YIELD nodes, relationships, properties, file, source,format, time 
RETURN *
// 4、导出图对象
CALL apoc.graph.fromDB('test',{}) yield graph 
CALL apoc.export.json.graph(graph, 'garph.json') 
YIELD nodes, relationships, properties, file, source,format, time 
RETURN *
// 5、给节点n设置json属性
CREATE (n) WITH n CALL apoc.convert.setJsonProperty(n, 'json', [1,2,3]) RETURN n

安装额外的插件,下载插件安装到plugin目录下 使用插件生成JSON-从CYPHER直接生成JSON【支持节点转换/属性转换/路径转换】

match (n) return casia.convert.json(n) limit 10
match p=(n)--() return casia.convert.json(p) limit 1
match (n) return casia.convert.json(properties(n)) limit 10

neo4j-graph-plugin下载

@crazyyanchao 谢谢你,其实我不是纠结在导出JSON文件,我是要直接导出的东西是json格式,然后里面有个嵌套,所以比较复杂。好像是要用到unwind,但是我不是很会用,想看看这方面的例子。

回到顶部