1. 程式人生 > >Titan學習筆記-API操作記錄

Titan學習筆記-API操作記錄

瞭解並學習一下Titan相關的JAVA API操作,以QQ、QQ群關係作為一個示例,記錄相關API的使用和操作。學習和了解的過程中,只用到了一小部分的API,後續有機會或有需求在做更新。

Titan官方的Document還是很好用,解釋和說明都非常的詳細,遇到相關問題可以隨時參考。

http://s3.thinkaurelius.com/docs/titan/0.9.0-M2/index.html

import org.apache.tinkerpop.gremlin.structure.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.thinkaurelius.titan.core.PropertyKey;
import com.thinkaurelius.titan.core.TitanFactory;
import com.thinkaurelius.titan.core.TitanFactory.Builder;
import com.thinkaurelius.titan.core.TitanGraph;
import com.thinkaurelius.titan.core.schema.Mapping;
import com.thinkaurelius.titan.core.schema.Parameter;
import com.thinkaurelius.titan.core.schema.TitanGraphIndex;
import com.thinkaurelius.titan.core.schema.TitanManagement;

public class TitanUtils {
	
	private Logger LOG = LoggerFactory.getLogger(TitanUtils.class);

	private TitanGraph graph = null;
	
	private TitanUtils() {
		loadTitanGraph();
	}
	
	private void loadTitanGraph() {
		Builder builder = TitanFactory.build();
		builder.set("storage.backend", "hbase");
        builder.set("storage.hostname", "host-124");
        builder.set("storage.port", "2181");
        //設定沒有作用
        builder.set("storage.tablename", "qqgraph");
        builder.set("atlas.graph.storage.hbase.table", "qqgraph");
        builder.set("index.search.backend", "elasticsearch");
        builder.set("index.search.hostname", "host-124");
        builder.set("index.search.port", "9300");
        //設定ES Index名稱
        builder.set("index.search.index-name", "qqgraph");
        /**
        builder.set("index.search.directory", "/tmp/titan" + File.separator + "es");  
        */
        builder.set("index.search.elasticsearch.interface", "TRANSPORT_CLIENT");
        builder.set("index.search.elasticsearch.cluster-name", "cisiondata-graphdb");
        builder.set("index.search.elasticsearch.local-mode", false);  
        builder.set("index.search.elasticsearch.client-only", true);
        builder.set("cache.db-cache", true);
        builder.set("cache.db-cache-clean-wait", 20);
        builder.set("cache.db-cache-time", 180000);
        builder.set("cache.db-cache-size", 0.25);
        builder.set("query.fast-property", true);
        builder.set("graph.set-vertex-id", false);
        this.graph = builder.open();
	}
	
	private static class TitanUtilsHolder {
		public static TitanUtils INSTANCE = new TitanUtils();
	}
	
	public static TitanUtils getInstance() {
		return TitanUtilsHolder.INSTANCE;
	}
	
	public TitanGraph getGraph() {
		if (null == graph) loadTitanGraph();
		return graph;
	}
	
	public void closeGraph() {
		if (null != graph) graph.close();
	}
	
	public TitanManagement openManagement() {
		return graph.openManagement();
	}
	
	public void commit(TitanManagement mgmt) {
		mgmt.commit();
	}
	
	public void rollback(TitanManagement mgmt) {
		mgmt.rollback();
	}
	
	/**
	 * 構建PropertyKey
	 * @param propertyKeyName
	 * @param propertyKeyType
	 * @return
	 */
	public PropertyKey buildPropertyKey(String propertyKeyName, Class<?> propertyKeyType) {
		TitanManagement mgmt = openManagement();
		PropertyKey propertyKey = null;
		try {
			propertyKey = buildPropertyKey(openManagement(), propertyKeyName, propertyKeyType);
			mgmt.commit();
	    } catch (Exception e) {
	    	LOG.error(e.getMessage(), e);
	        mgmt.rollback();
	    } 
		return propertyKey;
	}
	
	/**
	 * 構建PropertyKey
	 * @param mgmt
	 * @param propertyKeyName
	 * @param propertyKeyType
	 * @return
	 */
	public PropertyKey buildPropertyKey(TitanManagement mgmt, String propertyKeyName, Class<?> propertyKeyType) {
		return mgmt.containsPropertyKey(propertyKeyName) ? mgmt.getPropertyKey(propertyKeyName) :
			mgmt.makePropertyKey(propertyKeyName).dataType(propertyKeyType).make();
	}
	
	/**
	 * 構建PropertyKey並加入MixedIndex
	 * @param indexName
	 * @param elementType Vertex or Edge
	 * @param propertyKeyName
	 * @param propertyKeyType
	 * @param mapping  STRING -> not_analyzed TEXT -> tokenized TEXTSTRING -> both
	 */
	public void buildPropertyKeyWithMixedIndex(String indexName, Class<? extends Element> elementType, 
			String propertyKeyName, Class<?> propertyKeyType, Mapping mapping) {
		TitanManagement mgmt = openManagement();
		try {
	        PropertyKey propertyKey = buildPropertyKey(mgmt, propertyKeyName, propertyKeyType);
	        if (mgmt.containsGraphIndex(indexName)) {
	        	mgmt.addIndexKey(mgmt.getGraphIndex(indexName), propertyKey, 
	        		Parameter.of("mapping", mapping));
	        } else {
	        	mgmt.buildIndex(indexName, elementType).addKey(propertyKey, 
	        		Parameter.of("mapping", mapping)).buildMixedIndex("search");
	        }
	        mgmt.commit();
	    } catch (Exception e) {
	    	LOG.error(e.getMessage(), e);
	        mgmt.rollback();
	    } 
	}
	
	/**
	 * 構建EdgeLabel
	 * @param edgeLabel
	 */
	public void buildEdgeLabel(String edgeLabel) {
		TitanManagement mgmt = openManagement();
		try {
			if (!mgmt.containsEdgeLabel(edgeLabel)) {
				mgmt.makeEdgeLabel(edgeLabel).make();
			}
			mgmt.commit();
	    } catch (Exception e) {
	    	LOG.error(e.getMessage(), e);
	        mgmt.rollback();
	    } 
	}
	
	/**
	 * 構建Mixed索引
	 * @param indexName
	 * @param elementType
	 * @return
	 */
	public TitanGraphIndex buildMixedIndex(String indexName, Class<? extends Element> elementType) {
		TitanManagement mgmt = openManagement();
		TitanGraphIndex graphIndex = null;
		try {
			graphIndex = buildMixedIndex(mgmt, indexName, elementType);
			mgmt.commit();
	    } catch (Exception e) {
	    	LOG.error(e.getMessage(), e);
	        mgmt.rollback();
	    } 
		return graphIndex;
	}
	
	/**
	 * 構建Mixed索引
	 * @param mgmt
	 * @param indexName
	 * @param elementType
	 * @return
	 */
	public TitanGraphIndex buildMixedIndex(TitanManagement mgmt, String indexName, Class<? extends Element> elementType) {
		return mgmt.containsGraphIndex(indexName) ? mgmt.getGraphIndex(indexName) :
			mgmt.buildIndex(indexName, elementType).buildMixedIndex("search");
	}
	
}

import java.text.ParseException;

import org.apache.tinkerpop.gremlin.structure.Edge;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.cisiondata.utils.titan.TitanUtils;

import com.thinkaurelius.titan.core.schema.Mapping;

public class QQGraphUtils {
	
	public static void buildSchema() {	
		TitanUtils.getInstance().buildPropertyKeyWithMixedIndex("qqvertex", Vertex.class, "i1", String.class, Mapping.STRING);
		TitanUtils.getInstance().buildPropertyKeyWithMixedIndex("qqvertex", Vertex.class, "i6", String.class, Mapping.TEXTSTRING);
		TitanUtils.getInstance().buildPropertyKeyWithMixedIndex("qqvertex", Vertex.class, "i7", String.class, Mapping.TEXTSTRING);
		TitanUtils.getInstance().buildPropertyKeyWithMixedIndex("qqvertex", Vertex.class, "i8", String.class, Mapping.TEXTSTRING);
		TitanUtils.getInstance().buildPropertyKeyWithMixedIndex("qqvertex", Vertex.class, "i2", Integer.class, Mapping.STRING);
		TitanUtils.getInstance().buildPropertyKeyWithMixedIndex("qqvertex", Vertex.class, "i4", String.class, Mapping.STRING);
		
		TitanUtils.getInstance().buildPropertyKey("_id1", String.class);
		TitanUtils.getInstance().buildPropertyKey("i9", String.class);
		
		TitanUtils.getInstance().buildPropertyKeyWithMixedIndex("qunvertex", Vertex.class, "i10", String.class, Mapping.STRING);
		TitanUtils.getInstance().buildPropertyKeyWithMixedIndex("qunvertex", Vertex.class, "i11", String.class, Mapping.TEXT);
		TitanUtils.getInstance().buildPropertyKeyWithMixedIndex("qunvertex", Vertex.class, "i12", Integer.class, Mapping.STRING);
		TitanUtils.getInstance().buildPropertyKeyWithMixedIndex("qunvertex", Vertex.class, "i13", String.class, Mapping.TEXT);
		TitanUtils.getInstance().buildPropertyKeyWithMixedIndex("qunvertex", Vertex.class, "i14", String.class, Mapping.TEXT);
		TitanUtils.getInstance().buildPropertyKeyWithMixedIndex("qunvertex", Vertex.class, "i15", String.class, Mapping.STRING);
		
		TitanUtils.getInstance().buildPropertyKey("_id2", String.class);
		
		TitanUtils.getInstance().buildPropertyKeyWithMixedIndex("relationedge", Edge.class, "i5", String.class, Mapping.TEXTSTRING);
		
		TitanUtils.getInstance().buildEdgeLabel("including");
		
		TitanUtils.getInstance().closeGraph();
	}
	
	public static void main(String[] args) throws ParseException {
		QQGraphUtils.buildSchema();
	}
	
}

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
import org.apache.tinkerpop.gremlin.structure.Direction;
import org.apache.tinkerpop.gremlin.structure.Edge;
import org.apache.tinkerpop.gremlin.structure.Property;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.apache.tinkerpop.gremlin.structure.VertexProperty;
import org.cisiondata.modules.qqrelation.service.IQQGraphService;
import org.cisiondata.utils.exception.BusinessException;
import org.cisiondata.utils.json.GsonUtils;
import org.cisiondata.utils.titan.TitanUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.thinkaurelius.titan.core.TitanEdge;
import com.thinkaurelius.titan.core.TitanGraph;
import com.thinkaurelius.titan.core.TitanIndexQuery.Result;

@Service("qqGraphService")
public class QQGraphServiceImpl implements IQQGraphService {
	
	private Logger LOG = LoggerFactory.getLogger(QQGraphServiceImpl.class);
	
	private static final String NODE_QQ = "qq";
	private static final String NODE_QUN = "qun";
	private static final String _ID = "_id";
	private static final String QQ_ID = "_id1";
	private static final String QUN_ID = "_id2";
	private static final String QQ_NUM = "i1";
	private static final String QQ_AGE = "i2";
	private static final String QQ_AUTH = "i3";
	private static final String QQ_GENDER = "i4";
	private static final String QQ_NICKNAME = "i5";
	private static final String QQ_PASS = "i6";
	private static final String QQ_EMAIL = "i7";
	private static final String QQ_EPASS = "i8";
	private static final String QQ_CNOTE = "i9";
	private static final String QUN_NUM = "i10";
	private static final String QUN_NAME = "i11";
	private static final String QUN_PS = "i12";
	private static final String QUN_DESC = "i13";
	private static final String QUN_TYPE = "i14";
	private static final String QUN_CT = "i15";
	
	private static final String NICKNAME_QUERY = "e.i5:(%s)";
	
	private static Set<String> QQ_KEYS = new HashSet<String>();
	private static Set<String> QUN_KEYS = new HashSet<String>();
	
	static {
		QQ_KEYS.add(_ID);
		QQ_KEYS.add(QQ_ID);
		QQ_KEYS.add(QQ_NUM);
		QQ_KEYS.add(QQ_AGE);
		QQ_KEYS.add(QQ_GENDER);
		QQ_KEYS.add(QQ_PASS);
		QQ_KEYS.add(QQ_EMAIL);
		QQ_KEYS.add(QQ_EPASS);
		QQ_KEYS.add(QQ_CNOTE);
		QUN_KEYS.add(_ID);
		QUN_KEYS.add(QUN_ID);
		QUN_KEYS.add(QUN_NUM);
		QUN_KEYS.add(QUN_NAME);
		QUN_KEYS.add(QUN_PS);
		QUN_KEYS.add(QUN_DESC);
		QUN_KEYS.add(QUN_TYPE);
		QUN_KEYS.add(QUN_CT);
	}
	
	@Override
	public void insertQQNode(String nodeJSON) throws BusinessException {
		List<String> nodes = new ArrayList<String>();
		nodes.add(nodeJSON);
		insertQQNodes(nodes);
	}
	
	@Override
	public void insertQQNodes(List<String> nodes) throws BusinessException {
		if (null == nodes || nodes.size() == 0) return;
		TitanGraph graph = TitanUtils.getInstance().getGraph();
		try {
			for (int i = 0, len = nodes.size(); i < len; i++) {
				Map<String, Object> node = GsonUtils.fromJsonToMap(nodes.get(i));
				GraphTraversal<Vertex, Vertex> gt = graph.traversal().V().has(QQ_NUM, node.get(QQ_NUM));
				if (gt.hasNext()) {
					Vertex vertex = gt.next();
					Set<String> vertexPropertiesKeys = vertex.keys();
					if (vertexPropertiesKeys.contains(QQ_ID)) {
						VertexProperty<String> idVP = vertex.property(QQ_ID);
						String uniqueid = null != idVP.value() ? idVP.value() : "";
						if (!uniqueid.equals(node.get(_ID))) {
							LOG.error("qqnum {} has existed!", node.get(QQ_NUM));
						}
					}
				} else {
					Vertex vertex = graph.addVertex(NODE_QQ);
					for (Map.Entry<String, Object> entry : node.entrySet()) {
						String key = entry.getKey();
						Object value = entry.getValue();
						if (!QQ_KEYS.contains(key) || null == value) continue;
						if (_ID.equals(key)) {
							key = QQ_ID;
						} else if (QQ_AGE.equals(key)) {
							value = Integer.parseInt(String.valueOf(value));
						}
						vertex.property(key, value);
					}
				}
			}
			graph.tx().commit();
		} catch (Exception e) {
			LOG.error(e.getMessage(), e);
		}
	}
	
	@Override
	public void insertQQQunNode(String nodeJSON) throws BusinessException {
		List<String> nodes = new ArrayList<String>();
		nodes.add(nodeJSON);
		insertQQQunNodes(nodes);
	}
	
	@Override
	public void insertQQQunNodes(List<String> nodes) throws BusinessException {
		if (null == nodes || nodes.size() == 0) return;
		TitanGraph graph = TitanUtils.getInstance().getGraph();
		try {
			for (int i = 0, len = nodes.size(); i < len; i++) {
				Map<String, Object> node = GsonUtils.fromJsonToMap(nodes.get(i));
				GraphTraversal<Vertex, Vertex> gt = graph.traversal().V().has(QUN_NUM, node.get(QUN_NUM));
				if (gt.hasNext()) {
					Vertex vertex = gt.next();
					Set<String> vertexPropertiesKeys = vertex.keys();
					if (vertexPropertiesKeys.contains(QUN_ID)) {
						VertexProperty<String> idVP = vertex.property(QUN_ID);
						String uniqueid = null != idVP.value() ? idVP.value() : "";
						if (!uniqueid.equals(node.get(_ID))) {
							LOG.error("qunnum {} has existed!", node.get(QUN_NUM));
						}
					}
				} else {
					Vertex vertex = graph.addVertex(NODE_QUN);
					for (Map.Entry<String, Object> entry : node.entrySet()) {
						String key = entry.getKey();
						Object value = entry.getValue();
						if (!QUN_KEYS.contains(key) || null == value) continue;
						if (_ID.equals(key)) {
							key = QUN_ID;
						}else if (QUN_PS.equals(key)) {
							value = Integer.parseInt(String.valueOf(value));
						}
						vertex.property(key, value);
					}
				}
			}
			graph.tx().commit();
		}catch (Exception e) {
			LOG.error(e.getMessage(), e);
		}
	}
	
	@Override
	public void insertQQQunRelation(String nodeJSON) throws BusinessException {
		List<String> nodes = new ArrayList<String>();
		nodes.add(nodeJSON);
		insertQQQunRelations(nodes);
	}
	
	@Override
	public void insertQQQunRelations(List<String> nodes) throws BusinessException {
		if (null == nodes || nodes.size() == 0) return;
		TitanGraph graph = TitanUtils.getInstance().getGraph();
		try {
			for (int i = 0, len = nodes.size(); i < len; i++) {
				Map<String, Object> node = GsonUtils.fromJsonToMap(nodes.get(i));
				String qqNum = String.valueOf(node.get(QQ_NUM));
				String qunNum = String.valueOf(node.get(QUN_NUM));
				GraphTraversal<Vertex, Vertex> gt1 = graph.traversal().V().has(QQ_NUM, qqNum);
				Vertex qqVertex = null;
				if (gt1.hasNext()) {
					qqVertex = gt1.next();
				} else {
					qqVertex = graph.addVertex(NODE_QQ);
					qqVertex.property(QQ_NUM, qqNum);
				}
				GraphTraversal<Vertex, Vertex> gt2 = graph.traversal().V().has(QUN_NUM, qunNum);
				Vertex qunVertex = null;
				if (gt2.hasNext()) {
					qunVertex = gt2.next();
				} else {
					qunVertex = graph.addVertex(NODE_QUN);
					qunVertex.property(QUN_NUM, qunNum);
				}
				Edge includingEdge = qunVertex.addEdge("including", qqVertex);
				Object genderObj = node.get(QQ_GENDER);
				if (null != genderObj) {
					includingEdge.property(QQ_GENDER, genderObj);
				}
				Object ageObj = node.get(QQ_AGE);
				if (null != ageObj) {
					includingEdge.property(QQ_AGE, ageObj);
				}
				Object authObj = node.get(QQ_AUTH);
				if (null != authObj) {
					includingEdge.property(QQ_AUTH, authObj);
				}
				Object nicknameObj = node.get(QQ_NICKNAME);
				if (null != nicknameObj) {
					includingEdge.property(QQ_NICKNAME, nicknameObj);
				}
			}
			graph.tx().commit();
		} catch (Exception e) {
			LOG.error(e.getMessage(), e);
		}
	}
	
	@Override
	public List<Map<String, Object>> readQQNodeDataList(String qqNum) throws BusinessException {
		List<Map<String, Object>> resultList = new ArrayList<Map<String, Object>>();
		TitanGraph graph = TitanUtils.getInstance().getGraph();
		GraphTraversal<Vertex, Vertex> gt = graph.traversal().V().has(QQ_NUM, qqNum);
		while (gt.hasNext()) {
        	Map<String, Object> result = new HashMap<String, Object>();
			Vertex vertex = gt.next();
			Iterator<VertexProperty<Object>> vertexProperties = vertex.properties();
			while (vertexProperties.hasNext()) {
				VertexProperty<Object> vp = vertexProperties.next();
				result.put(vp.key(), vp.value());
			}
			List<Map<String, Object>> qunResultList = new ArrayList<Map<String, Object>>();
			Iterator<Edge> edgeIterator = vertex.edges(Direction.IN);
			while (edgeIterator.hasNext()) {
				Map<String, Object> qunResult = new HashMap<String, Object>();
				Edge edge = edgeIterator.next();
				Iterator<Property<Object>> edgeProperties = edge.properties();
				while (edgeProperties.hasNext()) {
					Property<Object> ep = edgeProperties.next();
					qunResult.put(ep.key(), ep.value());
				}
				Iterator<VertexProperty<Object>> outVertexProperties = edge.outVertex().properties();
				while (outVertexProperties.hasNext()) {
					VertexProperty<Object> ivp = outVertexProperties.next();
					qunResult.put(ivp.key(), ivp.value());
				}
				qunResultList.add(qunResult);
			}
			result.put("quns", qunResultList);
			resultList.add(result);
        }
		return resultList;
	}
	
	@Override
	public List<Map<String, Object>> readQQNodeDataListByNickname(String nickname) throws BusinessException {
		List<Map<String, Object>> resultList = new ArrayList<Map<String, Object>>();
		TitanGraph graph = TitanUtils.getInstance().getGraph();
		Iterator<Result<TitanEdge>> iterator = graph.indexQuery("relationedge", String.format(
			NICKNAME_QUERY, nickname)).offset(0).limit(50).edges().iterator();
		while (iterator.hasNext()) {
			Result<TitanEdge> result = iterator.next();
			TitanEdge edge = result.getElement();
			Iterator<Property<Object>> edgeProperties = edge.properties();
			Map<String, Object> finalResult = new HashMap<String, Object>();
			while (edgeProperties.hasNext()) {
				Property<Object> ep = edgeProperties.next();
				finalResult.put(ep.key(), ep.value());
			}
			Iterator<Vertex> vertices = edge.bothVertices();
			while (vertices.hasNext()) {
				Iterator<VertexProperty<Object>> inVertexProperties = vertices.next().properties();
				while (inVertexProperties.hasNext()) {
					VertexProperty<Object> ivp = inVertexProperties.next();
					finalResult.put(ivp.key(), ivp.value());
				}
			}
			finalResult.put("score", result.getScore());
			resultList.add(finalResult);
		}
		return resultList;
	}
	
	@Override
	public List<Map<String, Object>> readQunNodeDataList(String qunNum) throws BusinessException {
		List<Map<String, Object>> resultList = new ArrayList<Map<String, Object>>();
		TitanGraph graph = TitanUtils.getInstance().getGraph();
		GraphTraversal<Vertex, Vertex> gt = graph.traversal().V().has(QUN_NUM, qunNum);
        while (gt.hasNext()) {
        	Map<String, Object> result = new HashMap<String, Object>();
			Vertex vertex = gt.next();
			Iterator<VertexProperty<Object>> vertexProperties = vertex.properties();
			while (vertexProperties.hasNext()) {
				VertexProperty<Object> vp = vertexProperties.next();
				result.put(vp.key(), vp.value());
			}
			Iterator<Edge> edgeIterator = vertex.edges(Direction.OUT);
			List<Map<String, Object>> qqResultList = new ArrayList<Map<String, Object>>();
			while (edgeIterator.hasNext()) {
				Map<String, Object> qqResult = new HashMap<String, Object>();
				Edge edge = edgeIterator.next();
				Iterator<Property<Object>> edgeProperties = edge.properties();
				while (edgeProperties.hasNext()) {
					Property<Object> ep = edgeProperties.next();
					qqResult.put(ep.key(), ep.value());
				}
				Iterator<VertexProperty<Object>> inVertexProperties = edge.inVertex().properties();
				while (inVertexProperties.hasNext()) {
					VertexProperty<Object> ivp = inVertexProperties.next();
					qqResult.put(ivp.key(), ivp.value());
				}
				qqResultList.add(qqResult);
			}
			result.put("qqs:", qqResultList);
			resultList.add(result);
        }
		return resultList;
	}
	
}