了解并学习一下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;
}
}