分享一个neo4j数据封装类,这个类封装的JSON数据与neo4j的rest-api返回的数据格式类似。
- 负责区分不同查询
/**
* @param cypher@return
* @Description: TODO(跳过条件添加直接使用CYPHER查询 - 默认返回节点或者关系的所有属性字段)
*/
@Override
public JSONObject execute(String cypher, CRUD crudType) {
// 禁止某些危险查询
if (cypher.contains("DELETE") || cypher.contains("REMOVE") ||
cypher.contains("delete") || cypher.contains("remove")) {
this.logger.info("The cypher statement forbidden execution!", new IllegalAccessException());
return null;
}
long startMill = System.currentTimeMillis();
JSONArray queryResultList = new JSONArray();
Condition condition = new Condition();
condition.setStatement(cypher, this.contents);
queryResultList.add(Result.message(chooseSendCypherWay(condition, crudType)));
JSONObject result = Result.statistics(queryResultList);
// 统计所有请求的耗时,以及每个请求的平均耗时
long stopMill = System.currentTimeMillis();
result.put("consume", Result.statisticsConsume(startMill, stopMill, queryResultList.size(), this.logger));
if (ResultDataContents.D3_GRAPH.equals(this.contents) && !CRUD.RETRIEVE_PROPERTIES.equals(crudType)) {
result = JSONTool.packD3Json(result);
}
if (this.DEBUG) {
this.logger.info("Debug condition:" + condition.toString());
}
return result;
}
/**
* @param
* @return
* @Description: TODO(使用REST - API或者JAVA - DRIVER执行请求)
*/
public JSONObject chooseSendCypherWay(Condition condition, CRUD crudType) {
if (this.DEBUG) {
this.logger.info("Debug condition:" + condition.toString());
}
if (AccessOccurs.RESTFUL_API.equals(this.accessOccurs)) {
return JSONObject.parseObject(this.request.httpPost(NeoUrl.DB_DATA_TRANSACTION_COMMIT.getSymbolValue(), condition.toString()));
} else if (AccessOccurs.JAVA_DRIVER.equals(this.accessOccurs)) {
if (CRUD.RETRIEVE.equals(crudType)) {
return Neo4jDriver.searcher(this.driver, condition.getStatement(condition.toString()));
} else if (CRUD.MERGE_CSV.equals(crudType)) {
return Neo4jDriver.composerAutoCommit(this.driver, condition.getStatement(condition.toString()));
} else if (CRUD.RETRIEVE_PROPERTIES.equals(crudType)) {
return Neo4jDriver.rowProperties(this.driver, condition.getStatement(condition.toString()));
} else if (CRUD.MERGE_RETURN_NODE_ID.equals(crudType)) {
return Neo4jDriver.composerReturnNodeId(this.driver, condition.getStatement(condition.toString()));
} else {
return Neo4jDriver.composer(this.driver, condition.getStatement(condition.toString()));
}
}
return new JSONObject();
}
- Neo4jDriver负责数据封装
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;
/**
* @author YanchaoMa [email protected]
* @PACKAGE_NAME: casia.isi.neo4j.driver
* @Description: TODO(NEO4J_JAVA_DRIVER驱动)
* @date 2019/7/13 19:50
*/
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: 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 + "\r\n");
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 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: 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: 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 = transferObject(map);
resultArray.add(object);
}
} catch (Exception e) {
e.printStackTrace();
}
resultObject.put(CRUD.RETRIEVE_PROPERTIES.getSymbolValue(), resultArray);
return resultObject;
}
private static JSONObject transferObject(Map<String, Object> map) {
JSONObject object = new JSONObject();
for (String key : map.keySet()) {
Object value = map.get(key);
if (value instanceof Relationship) {
Relationship relationship = (Relationship) value;
JSONObject relation = packRelation(relationship);
object.put(key, relation);
} else if (value instanceof List) {
JSONArray array = transferArray(value);
object.put(key, array);
} else {
object.put(key, value);
}
}
return object;
}
private static JSONArray transferArray(Object value) {
List<Object> list = (List<Object>) value;
JSONArray array = new JSONArray();
for (Object object : list) {
if (object instanceof Relationship) {
JSONObject relation = packRelation((Relationship) object);
array.add(relation);
}else if (object instanceof Node){
JSONObject relation = packNode((Node) object);
array.add(relation);
}else {
array.add(object);
}
}
return array;
}
/**
* @param driver:传入NEO4J_JAVA驱动
* @param statement:cypher
* @return
* @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;
}
}
- 样例数据格式
{"totalNodeSize":3,"totalRelationSize":2,"consume":"Total consume 0s,average consume 0s/request","failed":0,"totalQuery":1,"message":true,"results":[{"data":[{"graph":{"relationships":[{"startNode":161,"id":40122,"type":"发帖","endNode":34650,"properties":{"relationType":"发帖","pub_time_mills":1573569457000,"update_time_mills":1582283028366}},{"startNode":497,"id":40123,"type":"转发","endNode":34650,"properties":{"pub_time_mills":1573575391000,"update_time_mills":1582283028366}}],"nodes":[{"id":161,"properties":{"_unique_uuid":"0cd911cea1f97c6ef610721ac81adc61","name":"Denise Ho (HOCC)","nameNodeSpace":"Denise Ho (HOCC)","update_time_mills":1582283028366},"labels":["TwitterID"]},{"id":34650,"properties":{"_unique_uuid":"e6c41e85e33ee38d826fcf2c0ba2d8b9","nameNodeSpace":"转推了","name":"转推了","update_time_mills":1582283028366},"labels":["Twitter发帖"]},{"id":497,"properties":{"_unique_uuid":"6fa25ec0b043445c144e44e33c57121d","loadRecommendEnginePathSize":6,"nameNodeSpace":"Wenli9187","name":"Wenli9187","update_time_mills":1582283148428},"labels":["TwitterID"]}],"properties":[]}}],"columns":["p"]}],"successful":1}