package com.wx.application.nebula.graph.service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.vesoft.nebula.client.graph.data.ResultSet;
import com.wx.application.constant.CONSTANT;
import com.wx.application.core.entity.OntologyConcept;
import com.wx.application.core.entity.OntologyRelation;
import com.wx.application.core.mapper.OntologyConceptMapper;
import com.wx.application.core.mapper.OntologyRelationMapper;
import com.wx.application.nebula.graph.base.BaseGraphSerice;
import com.wx.application.nebula.graph.base.Generators;
import com.wx.application.nebula.graph.base.ResultSetUtils;
import com.wx.application.nebula.graph.bean.ModelEdgeLine;
import com.wx.application.nebula.graph.bean.ModelVertex;
import com.wx.application.nebula.graph.bean.NebulaEdge;
import com.wx.application.nebula.graph.bean.NebulaEdgeLine;
import com.wx.application.nebula.graph.bean.NebulaField;
import com.wx.application.nebula.graph.bean.NebulaIndex;
import com.wx.application.nebula.graph.bean.NebulaTag;
import com.wx.application.nebula.graph.bean.NebulaVertex;
import com.wx.application.nebula.graph.enums.IndexType;
import com.wx.application.nebula.graph.query.NebulaModel;
import com.wx.application.nebula.graph.query.NebulaNode;
import com.wx.application.nebula.graph.query.NebulaPath;
import com.wx.application.nebula.graph.query.NebulaQo;
import com.wx.application.nebula.graph.query.NebulaRelation;
import com.wx.application.nebula.graph.query.PageRequest;
import com.wx.application.nebula.graph.query.TermQuery;
import com.wx.application.nebula.graph.query.TermQueryBuilder;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;

/**
 *本体模型
 */
@Slf4j
@Service
public class NebulaModelService extends BaseGraphSerice {
	
	@Autowired
	OntologyRelationMapper ontologyRelationMapper;
	
	@Autowired
	OntologyConceptMapper ontologyConceptMapper;
	
	/**
	 * 模型空间分割id
	 */
	final static String ONTOLOGYID = "ontologyId";
	final static String LABEL = "label";
	
	/**
     * 默认本体空间
     */
	final static String noumenon_space = "dn_noumenon_space";
	final static String noumenon_tag = "dn_noumenon_tag";
	final static String noumenon_edge = "dn_noumenon_edge";
    /**
     * 本体空间快照名称
     */
	final static String nebulafieldsnapshot = "nebulafieldsnapshot";
	

	protected NebulaVertex modelToNebulaVertex(ModelVertex mx) {
		NebulaVertex vertex = new NebulaVertex();
		Long ontologyId = mx.getOntologyId();
		vertex.setVid(mx.getVid());
		JSONObject ob = new JSONObject();
		ob.set(ONTOLOGYID, ontologyId);
		String tagName = Generators.tagname(mx.getLabel());
        ob.set("tagName", tagName);
        
        ob.set("label", mx.getLabel());
        /**
         * 加个字段快照
         */
        if(mx.getFields() != null) {
			ob.set(nebulafieldsnapshot, JSONUtil.toJsonStr(mx.getFields()));
		}
		vertex.setOb(ob);
		return vertex;
	}
	
	/**
	 * 插入模型点
	 * @param vertex
	 */
	public NebulaVertex insertModelVertex(ModelVertex mx) {
		NebulaVertex vertex = modelToNebulaVertex(mx);
		insertVertex(noumenon_space, noumenon_tag, vertex);
		return vertex;
	}
	
	
	public void insertBatchModelVertex(List<ModelVertex> mx) {
		
		if(mx == null) {
			return;
		}
		
		List<NebulaVertex> vtxs = new ArrayList<>();
		mx.forEach(v-> {
			try {
				NebulaVertex vtx = modelToNebulaVertex(v);
				vtxs.add(vtx);
				if(vtxs.size() > CONSTANT.nebula_batch_create_max) {
					insertTagAll(noumenon_space, noumenon_tag,  vtxs);
					vtxs.clear();
				}
			} catch (Exception e) {
				log.info("{}",e);
			}
		});
		
		if(vtxs.size() > 0) {
			insertTagAll(noumenon_space, noumenon_tag,  vtxs);
			vtxs.clear();
		}
	}
	
	/**
	 * 删除一个本体模型点
	 */
	public void deleteModelVertex(String vid) {
		deleteVertex(noumenon_space, vid);
	}
	
	/**
	 * 批量删除点
	 * @param vids
	 */
	public void deleteModelVertexs(List<String> vids) {
		deleteVertexs(noumenon_space, noumenon_tag, vids);
	}
	
	protected NebulaEdgeLine modelToNebulaEdge(ModelEdgeLine el) {
		NebulaEdgeLine edge = new NebulaEdgeLine();
		
		Long ontologyId = el.getOntologyId();
		
		edge.setSrcId(el.getSrcId());
		edge.setDstId(el.getDstId());
		
		edge.setEdgeNo(el.getEdgeNo());
		JSONObject ob = new JSONObject();
		ob.set(ONTOLOGYID, ontologyId);
		
		String edgeName = Generators.edgename(el.getLabel());
		
        ob.set("edgeName", edgeName);
        ob.set("label", el.getLabel());
        /*ob.set("arrow", el.getArrow());
        ob.set("paternity", el.getPaternity());*/
        /**
         * 加个快照
         */
        ob.set(nebulafieldsnapshot, JSONUtil.toJsonStr(el.getFields()));
		edge.setOb(ob);
		return edge;
	}
	/**
	 * 创建一个模型关系
	 */
	public NebulaEdgeLine insertModelEdge(ModelEdgeLine el) {
		NebulaEdgeLine edge = modelToNebulaEdge(el);
		insertEdgeLine(noumenon_space, noumenon_edge, edge);
		return edge;
	}
	
	
	public void insertBatchModelEdge(List<ModelEdgeLine> mx) {
		
		if(mx == null) {
			return;
		}
		
		List<NebulaEdgeLine> vtxs = new ArrayList<>();
		mx.forEach(v-> {
			try {
				NebulaEdgeLine vtx = modelToNebulaEdge(v);
				vtxs.add(vtx);
				if(vtxs.size() > CONSTANT.nebula_batch_create_max) {
					insertEdgeLineAll(noumenon_space, noumenon_edge,  vtxs);
					vtxs.clear();
				}
			} catch (Exception e) {
				log.info("{}",e);
			}
		});
		
		if(vtxs.size() > 0) {
			insertEdgeLineAll(noumenon_space, noumenon_edge,  vtxs);
			vtxs.clear();
		}
	}
	
	
	/**
	 * 删除一个本体模型点
	 */
	public void deleteModelEdge(NebulaEdgeLine edge) {
		deleteEdgeLine(noumenon_space, noumenon_edge, edge);
	}
	
	
	/**
     * 根据OntologyId删除所有的本体和关系
     */
    public void deleteAllByOntologyId(Long ontologyId) {
    	TermQueryBuilder builder = new TermQueryBuilder();
    	builder.add(TermQueryBuilder.termMust(ONTOLOGYID, TermQuery.Operator.EQ, ontologyId));
    	deleteVertexConduit(noumenon_space, noumenon_tag, builder);
    }
	
    
    /**
	 * 根据条件统计点
	 */
    public Long countVertexsByOntologyid(Long ontologyId) {
    	TermQueryBuilder builder = new TermQueryBuilder();
    	builder.add(TermQueryBuilder.termMust(ONTOLOGYID, TermQuery.Operator.EQ, ontologyId));
    	return countVertexs(noumenon_space, noumenon_tag, builder);
    }
    
    /**
	 * 根据条件统计边
	 */
    public Long countEdgesByOntologyid(Long ontologyId) {
    	TermQueryBuilder builder = new TermQueryBuilder();
    	builder.add(TermQueryBuilder.termMust(ONTOLOGYID, TermQuery.Operator.EQ, ontologyId));
    	return countEdges(noumenon_space, noumenon_edge, builder);
    }
    
    /**
	 * 根据对象属性名称统计开始节点和 结束节点的数量
	 */
    public List<JSONObject> groupCountVexByEdgeByOntologyid(Long ontologyId) {
    	
    	TermQueryBuilder builder = new TermQueryBuilder();
    	builder.add(TermQueryBuilder.termMust(ONTOLOGYID, TermQuery.Operator.EQ, ontologyId));
    	
    	/**
		 * 通用聚合统计
		 * 根据关键统计开始节点和 结束节点的数量
		 */
		String nGql = "LOOKUP ON {} "
				+ "YIELD dst(edge) AS DstVID,src(edge) AS "
				+ "SrcVID,dn_noumenon_edge.label as label | "
				+ "GROUP BY $-.label YIELD $-.label as relation, "
				+ "count(DISTINCT $-.DstVID ) AS dstCount, "
				+ "count(DISTINCT $-.SrcVID ) AS srcCount | ORDER BY $-.srcCount DESC";
		
		String query = null;
		if(builder != null && StringUtils.isNotBlank(query = builder.of(noumenon_edge))) {
			nGql = nGql.replaceFirst("YIELD", " {} YIELD");
			nGql = StrUtil.format(nGql, noumenon_edge, query);
		}
		ResultSet resultSet = executeGql(noumenon_space, nGql);
		
		List<JSONObject> ntls = ResultSetUtils.printResultObject(resultSet,3);
    	
		Map<String,JSONObject> nMap = new HashMap<>();
		
		if(ntls != null && ntls.size() > 0) {
			for(JSONObject fn : ntls) {
				nMap.put(fn.getStr("relation"), fn);
			}
		}
		
		QueryWrapper<OntologyRelation> wrapper = new QueryWrapper();
		wrapper.eq("ontology_id", ontologyId);
		List<OntologyRelation> ontologyRelations = ontologyRelationMapper.selectList(wrapper);
		
		List<JSONObject> result = new ArrayList<>();
		if(ontologyRelations != null && ontologyRelations.size() > 0) {
			ontologyRelations.forEach(v-> {
				JSONObject it = new JSONObject();
				it.set("relation", v.getLabel());
				JSONObject cs = nMap.get(v.getLabel());
				if(cs != null) {
					it.set("dstcount", cs.getInt("dstcount"));
					it.set("srccount", cs.getInt("srccount"));
				} else {
					it.set("dstcount", 0);
					it.set("srccount", 0);
				}
				result.add(it);
			});
		}
		
		return result;
    }

    
    /**
     * 根据label标签查询关系
     */
    public List<NebulaRelation> findRelationsByLabel(String label) {
    	TermQueryBuilder builder = new TermQueryBuilder();
    	builder.add(TermQueryBuilder.termMust(LABEL, TermQuery.Operator.EQ, label));
    	return findRelations(noumenon_space, noumenon_edge, builder);
    }
    
    /**
     * 根据id结婚查询概念
     * @param vids
     * @return
     */
    public List<NebulaNode> findNodeByIds(List<String> vids) {
    	return findNodeByIds(noumenon_space, noumenon_tag, vids);
    }
    
    /**
     * 根据模型id查询
     * @return
     */
    public List<NebulaNode> findNodesByOntologyId(Long ontologyId) {
    	TermQueryBuilder builder = new TermQueryBuilder();
    	builder.add(TermQueryBuilder.termMust(ONTOLOGYID, TermQuery.Operator.EQ, ontologyId));
    	/**
    	 * 查询模型的节点
    	 */
		return findNodes(noumenon_space, noumenon_tag, builder);
    }
    

    public NebulaModel findAllGraphByOntologyId(Long ontologyId) {
    	TermQueryBuilder builder = new TermQueryBuilder();
    	builder.add(TermQueryBuilder.termMust(ONTOLOGYID, TermQuery.Operator.EQ, ontologyId));
    	/**
    	 * 分页查询查询模型关系
    	 */
    	List<NebulaRelation> relations = findRelations(noumenon_space, 
    			noumenon_edge, builder);
    	
    	List<NebulaNode> nodes = findNodes(noumenon_space, noumenon_tag, builder);
    	
    	NebulaModel result = new NebulaModel();
		result.setNodes(nodes);
		result.setRelations(relations);

		return result;
    }
    
    /**
     * 根据OntologyId查询的本体和关系，用户图谱展示
     */
    public NebulaModel findRelationByOntologyId(Long ontologyId, NebulaQo nQ) {
    	
    	TermQueryBuilder builder = new TermQueryBuilder();
    	builder.add(TermQueryBuilder.termMust(ONTOLOGYID, TermQuery.Operator.EQ, ontologyId));
    	
    	/**
    	 * 分页查询
    	 */
    	PageRequest pageRequest = null;
    	if(nQ.getPageFlag()) {
    		pageRequest = PageRequest.of(nQ.getPage(), nQ.getPageSize());
    	}
    	
    	/**
    	 * 分页查询查询模型关系
    	 */
    	List<NebulaRelation> relations = findRelations(noumenon_space, 
    			noumenon_edge, builder, pageRequest);
    	
    	List<NebulaNode> nodes = null;
    	if(relations.size() > 0) {
    		List<String> vids = new ArrayList<>();
    		for(NebulaRelation fn : relations) {
    			vids.add(fn.getSrcId());
    			vids.add(fn.getDstId());
    		}
    		nodes = findNodeByIds(noumenon_space, noumenon_tag, vids);
    	} 
    	
    	if(nodes == null || nodes.size() == 0) {
    		builder = new TermQueryBuilder();
        	builder.add(TermQueryBuilder.termMust(ONTOLOGYID, TermQuery.Operator.EQ, ontologyId));
    		nodes = findNodes(noumenon_space, noumenon_tag, builder, pageRequest);
    	}

		NebulaModel result = new NebulaModel();
		result.setNodes(nodes);
		result.setRelations(relations);
		
		return result;
    }
    
    
    /**
     * 复制图模型
     */
    public void copyByOntologyId(Long srcOntologyId, Long dictOntologyId) {
    	
    	/**
    	 * 查询模型关系
    	 */
    	TermQueryBuilder builder = new TermQueryBuilder();
    	builder.add(TermQueryBuilder.termMust(ONTOLOGYID, TermQuery.Operator.EQ, srcOntologyId));

    	List<NebulaRelation> relations = findRelations(noumenon_space, noumenon_edge, builder);
    	
    	/**
    	 * 查询模型的节点
    	 */
		List<NebulaNode> nodes = findNodes(noumenon_space, noumenon_tag, builder);
    	
		Map<String,String> vidMap = new HashMap<>();
		
		List<NebulaVertex> vertexs = new ArrayList<>();
		
    	nodes.forEach(v->{
    		
    		try {
    			
    			String srcId = v.getVid();
    			String qzDctId = dictOntologyId + "_";
    			final Pattern pattern = Pattern.compile("(\\d+)_", Pattern.DOTALL);
    			String dctId = ReUtil.replaceFirst(pattern, srcId, qzDctId);
    			
    			
	    		JSONObject ob = v.getProperties();
	    		/**
	    		 * 赋值新的模型空间id
	    		 */
	    		ob.set(ONTOLOGYID, dictOntologyId);
	    		NebulaVertex vx = new NebulaVertex();
	    		vx.setOb(ob);
	    		vx.setVid(dctId);
	    		
	    		vertexs.add(vx);
	    		if(vertexs.size() > 2000) {
	    			insertTagAll(noumenon_space, noumenon_tag, vertexs);
	    			vertexs.clear();
	    		}
	    		/**
	    		 * 老的vid 和 新vid进行对应
	    		 */
	    		vidMap.put(srcId, dctId);
    		} catch (Exception e) {
				log.error("{}",e);
			}
    	});
    	
    	if(vertexs.size() > 0) {
			insertTagAll(noumenon_space, noumenon_tag, vertexs);
			vertexs.clear();
		}
    	
    	/**
    	 * 插入关系
    	 */
    	
    	List<NebulaEdgeLine> edges = new ArrayList<>();
    	relations.forEach(v->{
    		
    		try {
	    		String srcId = v.getSrcId();
	    		String dstId = v.getDstId();
	    		JSONObject ob = v.getProperties();
	    		/**
	    		 * 赋值新的模型空间id
	    		 */
	    		ob.set(ONTOLOGYID, dictOntologyId);
	    		
	    		NebulaEdgeLine edge = new NebulaEdgeLine();
	    		edge.setSrcId(vidMap.get(srcId));
	    		edge.setDstId(vidMap.get(dstId));
	    		edge.setOb(ob);
	    		edges.add(edge);
	    		
	    		if(edges.size() > 2000) {
	    			insertEdgeLineAll(noumenon_space, noumenon_edge, edges);
	    			edges.clear();
	    		}
	    		
    		} catch (Exception e) {
    			log.error("{}",e);
			}
    	});
    	
    	if(edges.size() > 0) {
			insertEdgeLineAll(noumenon_space, noumenon_edge, edges);
			edges.clear();
		}
    }
    
    /**
	 * 根据本体模型创建图空间
	 */
	public void initGraphDatabase(Long ontologyId, String space) {
		/**
    	 * 查询模型关系
    	 */
    	TermQueryBuilder builder = new TermQueryBuilder();
    	builder.add(TermQueryBuilder.termMust(ONTOLOGYID, TermQuery.Operator.EQ, ontologyId));

    	/**
    	 * 查询模型的节点
    	 */
		List<NebulaNode> nodes = findNodes(noumenon_space, noumenon_tag, builder);
		
		int tn = 20;
		
		List<List<NebulaNode>> lists = ListUtil.split(nodes, (nodes.size() / tn) + 1);
		ExecutorService executor = Executors.newFixedThreadPool(tn);
		
		for(List<NebulaNode> fn : lists) {
        	executor.submit(new Runnable() {
                @Override
                public void run() {
                	fn.forEach(v->{
                		try {
                			JSONObject ob = v.getProperties();
                			String tagName = ob.getStr("tagName");
                			String comment = ob.getStr("label");
                			JSONArray napshot = ob.getJSONArray(nebulafieldsnapshot);
                			NebulaTag tag = new NebulaTag();
            				tag.setName(tagName);
            				tag.setComment(comment);
            				
                			if(napshot != null) {
                				List<NebulaField> fields = napshot.toList(NebulaField.class);
                				tag.setFields(fields);
                			}
                			
                			createTag(space, tag);

                			NebulaIndex e = new NebulaIndex();
                			e.setName(Generators.indextagname(tagName));
                			e.setOnName(tagName);
                			e.setType(IndexType.TAG);
                			createIndex(space, e);
                			
                		} catch (Exception e) {
                			log.error("{}",e);
            			}
            		});
                }
    		});
        }
        
        executor.shutdown();
        try {
			if (!executor.awaitTermination(60, TimeUnit.MINUTES)) {
			    
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		List<NebulaRelation> relations = findRelations(noumenon_space, noumenon_edge, builder);
		
		QueryWrapper<OntologyRelation> wrapper = new QueryWrapper();
		wrapper.eq("ontology_id", ontologyId);
		List<OntologyRelation> ontologyRelations = ontologyRelationMapper.selectList(wrapper);
		
		List<String> rls = ontologyRelations.stream().map(OntologyRelation::getLabel).collect(Collectors.toList());
		
		Map<String, JSONArray> fieldMaps = new ConcurrentHashMap<>();
		Map<String, String> edgeMaps = new ConcurrentHashMap<>();
		
		relations.forEach(v->{
			try {
    			JSONObject ob = v.getProperties();
    			String edgeName = ob.getStr("edgeName");
    			String comment = ob.getStr("label");
    			JSONArray napshot = ob.getJSONArray(nebulafieldsnapshot);
    			edgeMaps.put(comment, edgeName);
    			if(napshot != null && napshot.size() > 0) {
    				if(!fieldMaps.containsKey(comment)) {
        				fieldMaps.put(comment, new JSONArray());
        			}
    				fieldMaps.get(comment).addAll(napshot);
    			}
    		} catch (Exception e) {
    			log.error("{}",e);
			}
		});
		
		
		List<List<String>> rts = ListUtil.split(rls, (rls.size() / tn) + 1);
		executor = Executors.newFixedThreadPool(tn);
		
		for(List<String> fn : rts) {
        	executor.submit(new Runnable() {
                @Override
                public void run() {
                	fn.forEach(comment->{
                		try {
            				
            				NebulaEdge edge = new NebulaEdge();
            				
            				String edgeName = edgeMaps.get(comment);
            				edgeName = StringUtils.isBlank(edgeName)?Generators.edgename(comment):edgeName;
            				JSONArray napshot = fieldMaps.get(comment);
            				
            				if(napshot != null && napshot.size() > 0) {
                				List<NebulaField> fields = napshot.toList(NebulaField.class);
                				edge.setFields(fields);
                			}

            				edge.setName(edgeName);
            				edge.setComment(comment);
                			
                			createEdge(space, edge);
                			
                			/**
                			 * 创建索引
                			 */
                			NebulaIndex e = new NebulaIndex();
                			e.setName(Generators.indexedgename(edgeName));
                			e.setOnName(edgeName);
                			e.setType(IndexType.EDGE);
                			createIndex(space, e);
                			
                		} catch (Exception e) {
                			log.error("{}",e);
            			}
            		});
                }
    		});
        }
        
        executor.shutdown();
        try {
			if (!executor.awaitTermination(60, TimeUnit.MINUTES)) {
			    
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

	}

	/**
	 * 根据id查找节点
	 */
	public NebulaNode findNodeById(String vid) {
		return findNodeById(noumenon_space, noumenon_tag, vid);
	}
	
	
	public List<NebulaPath> findListPathById(String vid) {
		
		NebulaModel model = findOnePathById(noumenon_space , vid);
		
		List<NebulaNode> nodes = model.getNodes();
		
		Map<String, NebulaNode> nodeMap = nodes.stream()
                .collect(Collectors.toMap(NebulaNode::getVid, 
                		node-> node, (oldValue, newValue) -> newValue));
		
		List<NebulaRelation> relations = model.getRelations();
		
		List<NebulaPath> result = new ArrayList<>();
		
		relations.forEach(v -> {
			if(nodeMap.containsKey(v.getSrcId()) 
					&& nodeMap.containsKey(v.getDstId())) {
				NebulaPath pth = new NebulaPath();
				pth.setSrcnode(nodeMap.get(v.getSrcId()));
				pth.setDctnode(nodeMap.get(v.getDstId()));
				pth.setRelation(v);
				result.add(pth);
			}
		});
		
		return result;
	}
	
	
	/**
	 * 根据id查找path
	 */
	public NebulaModel findPathById(Long ontologyId, String vid) {

		NebulaModel model = findOnePathById(noumenon_space , vid);
		if(model.getNodes().size() == 0) {
			NebulaNode node = findNodeById(vid);
			if(node != null) {
				model.getNodes().add(node);
			}
		}
		
		/**
		 * 从mysql中构建树形图谱
		 */
		QueryWrapper<OntologyConcept> wrapper = new QueryWrapper();
		wrapper.eq("own_id", vid);
		OntologyConcept own = ontologyConceptMapper.selectOne(wrapper);
		
		findparentOntologyConcept(ontologyId, own, model);
		
		Set<NebulaRelation> srls = new HashSet<>(model.getRelations());
		Set<NebulaNode> snls = new HashSet<>(model.getNodes());
		
		model.setNodes(new ArrayList<>(snls));
		model.setRelations(new ArrayList<>(srls));
		return model;
	}
	
	/**
	 * 递归查找父亲id
	 */
	public void findparentOntologyConcept(Long ontologyId, OntologyConcept own, NebulaModel model) {
		QueryWrapper<OntologyConcept> wrapper = new QueryWrapper();
		wrapper.eq("own_id", own.getParentId());
		OntologyConcept pa = ontologyConceptMapper.selectOne(wrapper);
		if(pa != null) {
			
			NebulaRelation relation = new NebulaRelation();
			relation.setSrcId(own.getOwnId());
			relation.setDstId(own.getParentId());
			relation.setEdgeName(noumenon_edge);
			
			JSONObject properties = new JSONObject();
			properties.set("edgeName", Generators.edgename("父概念"));
			properties.set("label", "父概念");
			properties.set("arrow", true);
			properties.set(ONTOLOGYID, ontologyId);
			relation.setProperties(properties);
			model.getRelations().add(relation);
			
			NebulaNode node = new NebulaNode();
			node.setVid(pa.getOwnId());
			node.setLabels(noumenon_tag);
			
			properties = new JSONObject();
			properties.set("label", pa.getLabel());
			properties.set("tagName", Generators.tagname(pa.getLabel()));
			properties.set(ONTOLOGYID, ontologyId);
			node.setProperties(properties);
			model.getNodes().add(node);
			
			findparentOntologyConcept(ontologyId, pa, model);
		}
	}
	
	
	/**
	 * 递归
	 * 查询当前节点的值属性，包含继承的值属性
	 */
	public List<NebulaField> findNebulaFieldWithParents(String vId) {
		
		QueryWrapper<OntologyConcept> wrapper = new QueryWrapper();
		wrapper.eq("own_id", vId);
		OntologyConcept own = ontologyConceptMapper.selectOne(wrapper);
		List<String> conceptIds = null;
		if(own != null) {
			conceptIds = new ArrayList<>();
			conceptIds.add(own.getOwnId());
			findConceptWithParents(own, conceptIds);
		}
		
		/**
		 * 查询属性
		 */
		List<NebulaNode> nodes = super.findNodeByIds(noumenon_space, noumenon_tag, conceptIds);
		
		List<NebulaField> fds = new ArrayList<>();
		
		nodes.forEach(v-> {
			JSONObject ob = v.getProperties();
			JSONArray napshot = ob.getJSONArray(nebulafieldsnapshot);
			if(napshot != null) {
				List<NebulaField> fields = napshot.toList(NebulaField.class);
				fds.addAll(fields);
			}
		});
		
		//java8根据对象属性去重
        List<NebulaField> unique = fds.stream().collect(
        		Collectors.collectingAndThen(
                		Collectors.toCollection(() -> new TreeSet<>(
                				Comparator.comparing(NebulaField::getField))),ArrayList::new));
		return unique;
	}
	
	/**
	 * 递归
	 */
	public void findConceptWithParents(OntologyConcept own, List<String> conceptIds) {
		QueryWrapper<OntologyConcept> wrapper = new QueryWrapper();
		wrapper.eq("own_id", own.getParentId());
		OntologyConcept pa = ontologyConceptMapper.selectOne(wrapper);
		if(pa != null) {
			conceptIds.add(pa.getOwnId());
			findConceptWithParents(pa, conceptIds);
		}
	}
	
	
	/**
	 * 通过对象属性名称查询所有的path
	 */
	public NebulaModel findPathByEdgeLabel(Long ontologyId,String label) {
		/**
    	 * 查询模型关系
    	 */
		String nGql = "match p=(v)-[r:{}]->(v1) where r.{}==\"{}\" and r.{}=={} return p ";
		nGql = StrUtil.format(nGql, noumenon_edge, LABEL, label,ONTOLOGYID,ontologyId);
		ResultSet resultSet = executeGql(noumenon_space, nGql);
		return ResultSetUtils.printResultPath(resultSet);
	}
	
	/**
	 * 通过对象属性名称查询所有的path
	 */
	public List<NebulaNode> findNodesbyField(Long ontologyId, String field) {
		
		List<NebulaNode> result = new ArrayList<>();
		TermQueryBuilder builder = new TermQueryBuilder();
    	builder.add(TermQueryBuilder.termMust(ONTOLOGYID, TermQuery.Operator.EQ, ontologyId));
    	List<NebulaNode> nodes = findNodes(noumenon_space, noumenon_tag, builder);
    	
    	for(NebulaNode fn : nodes) {
    		JSONArray arr = fn.getProperties().getJSONArray(nebulafieldsnapshot);
    		if(arr != null) {
    			List<NebulaField> fields = arr.toList(NebulaField.class);
    			fields.forEach(v-> {
    				String key = v.getField();
    				if(field.equals(key)) {
    					result.add(fn);
    				}
    			});
    		}
    	}
		return result;
	}
	
	
	/**
	 * 图空间的值属性数量分组聚合
	 */
	public List<Map> groupFieldByOntologyId(Long ontologyId) {
		
		TermQueryBuilder builder = new TermQueryBuilder();
    	builder.add(TermQueryBuilder.termMust(ONTOLOGYID, TermQuery.Operator.EQ, ontologyId));

		/**
		 * 统计值属性数量
		 */
    	List<NebulaNode> nodes = findNodes(noumenon_space, noumenon_tag, builder);
    	
    	Map<String,Integer> mapCount = new HashMap<>();
    	Map<String,NebulaField> mapField = new HashMap<>();
    	
    	for(NebulaNode fn : nodes) {
    		JSONArray arr = fn.getProperties().getJSONArray(nebulafieldsnapshot);
    		if(arr != null) {
    			List<NebulaField> fields = arr.toList(NebulaField.class);
    			fields.forEach(v-> {
    				String key = v.getField();
    				Integer cc = mapCount.get(key);
    				if(cc == null) {
    					cc = 0;
    				}
    				cc += 1;
    				mapCount.put(key, cc);
    				mapField.put(key, v);
    			});
    		}
    	}
    	
    	List<Map> fls = new ArrayList<>();
    	for(NebulaField field : mapField.values()) {
    		Map<String, Object> fp = BeanUtil.beanToMap(field);
    		fp.put("count", mapCount.get(field.getField()));
    		fls.add(fp);
    	}

    	return fls;
	}
}
