Commit ec8177bb by TJBChris

Moved Graph accesses and search walker function to

org.apache.hadoop.metadata.discovery.GraphBackedDiscoveryService. Will need additional clean up, but the functionality remains the same.
parent c1e20f8d
...@@ -20,6 +20,7 @@ package org.apache.hadoop.metadata.discovery; ...@@ -20,6 +20,7 @@ package org.apache.hadoop.metadata.discovery;
import org.apache.hadoop.metadata.MetadataException; import org.apache.hadoop.metadata.MetadataException;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
...@@ -39,4 +40,8 @@ public interface DiscoveryService { ...@@ -39,4 +40,8 @@ public interface DiscoveryService {
*/ */
List<Map<String,String>> searchByGremlin(String gremlinQuery) throws MetadataException; List<Map<String,String>> searchByGremlin(String gremlinQuery) throws MetadataException;
Map<String, HashMap<String,Map<String,String>>> textSearch(String searchText, int depth, String prop);
Map<String, HashMap<String,Map<String,String>>> relationshipWalk(String guid, int depth, String edgesToFollow);
} }
...@@ -19,10 +19,13 @@ ...@@ -19,10 +19,13 @@
package org.apache.hadoop.metadata.discovery; package org.apache.hadoop.metadata.discovery;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import org.apache.hadoop.metadata.MetadataException; import org.apache.hadoop.metadata.MetadataException;
import org.apache.hadoop.metadata.repository.MetadataRepository; import org.apache.hadoop.metadata.repository.MetadataRepository;
import javax.inject.Inject; import javax.inject.Inject;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
...@@ -50,4 +53,23 @@ public class GraphBackedDiscoveryService implements DiscoveryService { ...@@ -50,4 +53,23 @@ public class GraphBackedDiscoveryService implements DiscoveryService {
// simple pass-through // simple pass-through
return repository.searchByGremlin(gremlinQuery); return repository.searchByGremlin(gremlinQuery);
} }
@Override
public Map<String, HashMap<String,Map<String,String>>> textSearch(String searchText, int depth, String prop) {
Preconditions.checkNotNull(searchText, "Invalid argument: \"text\" cannot be null.");
Preconditions.checkNotNull(prop, "Invalid argument: \"prop\" cannot be null.");
return repository.textSearch(searchText, depth, prop);
}
@Override
public Map<String, HashMap<String,Map<String,String>>> relationshipWalk(String guid, int depth, String edgesToFollow) {
Preconditions.checkNotNull(guid, "Invalid argument: \"guid\" cannot be null.");
Preconditions.checkNotNull(edgesToFollow, "Invalid argument: \"edgesToFollow\" cannot be null.");
return repository.relationshipWalk(guid, depth, edgesToFollow);
}
} }
...@@ -24,6 +24,7 @@ import org.apache.hadoop.metadata.MetadataException; ...@@ -24,6 +24,7 @@ import org.apache.hadoop.metadata.MetadataException;
import org.apache.hadoop.metadata.service.Service; import org.apache.hadoop.metadata.service.Service;
import org.apache.hadoop.metadata.storage.RepositoryException; import org.apache.hadoop.metadata.storage.RepositoryException;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
...@@ -49,4 +50,7 @@ public interface MetadataRepository extends Service { ...@@ -49,4 +50,7 @@ public interface MetadataRepository extends Service {
* @throws org.apache.hadoop.metadata.MetadataException * @throws org.apache.hadoop.metadata.MetadataException
*/ */
List<Map<String,String>> searchByGremlin(String gremlinQuery) throws MetadataException; List<Map<String,String>> searchByGremlin(String gremlinQuery) throws MetadataException;
Map<String,HashMap<String,Map<String,String>>> textSearch(String searchText, int depth, String prop);
Map<String,HashMap<String,Map<String,String>>> relationshipWalk(String guid, int depth, String edgesToFollow);
} }
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
package org.apache.hadoop.metadata.repository.graph; package org.apache.hadoop.metadata.repository.graph;
import com.google.common.base.Preconditions;
import com.thinkaurelius.titan.core.TitanGraph; import com.thinkaurelius.titan.core.TitanGraph;
import com.thinkaurelius.titan.core.TitanProperty; import com.thinkaurelius.titan.core.TitanProperty;
import com.thinkaurelius.titan.core.TitanVertex; import com.thinkaurelius.titan.core.TitanVertex;
...@@ -26,6 +27,8 @@ import com.tinkerpop.blueprints.Edge; ...@@ -26,6 +27,8 @@ import com.tinkerpop.blueprints.Edge;
import com.tinkerpop.blueprints.GraphQuery; import com.tinkerpop.blueprints.GraphQuery;
import com.tinkerpop.blueprints.TransactionalGraph; import com.tinkerpop.blueprints.TransactionalGraph;
import com.tinkerpop.blueprints.Vertex; import com.tinkerpop.blueprints.Vertex;
import org.apache.commons.collections.iterators.IteratorChain;
import org.apache.hadoop.metadata.IReferenceableInstance; import org.apache.hadoop.metadata.IReferenceableInstance;
import org.apache.hadoop.metadata.ITypedInstance; import org.apache.hadoop.metadata.ITypedInstance;
import org.apache.hadoop.metadata.ITypedReferenceableInstance; import org.apache.hadoop.metadata.ITypedReferenceableInstance;
...@@ -52,6 +55,7 @@ import javax.script.Bindings; ...@@ -52,6 +55,7 @@ import javax.script.Bindings;
import javax.script.ScriptEngine; import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager; import javax.script.ScriptEngineManager;
import javax.script.ScriptException; import javax.script.ScriptException;
import java.io.IOException; import java.io.IOException;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.BigInteger; import java.math.BigInteger;
...@@ -180,6 +184,140 @@ public class GraphBackedMetadataRepository implements MetadataRepository { ...@@ -180,6 +184,140 @@ public class GraphBackedMetadataRepository implements MetadataRepository {
return entityList; return entityList;
} }
private static void searchWalker (Vertex vtx, final int max, int counter, HashMap<String,Map<String,String>> e, HashMap<String,Map<String,String>> v, String edgesToFollow) {
counter++;
if (counter <= max) {
Map<String,String> jsonVertexMap = new HashMap<String,String>();
Iterator<Edge> edgeIterator = null;
// If we're doing a lineage traversal, only follow the edges specified by the query. Otherwise
// return them all.
if (edgesToFollow != null) {
IteratorChain ic = new IteratorChain();
for (String iterateOn: edgesToFollow.split(",")){
ic.addIterator(vtx.query().labels(iterateOn).edges().iterator());
}
edgeIterator = ic;
} else {
edgeIterator = vtx.query().edges().iterator();
}
//Iterator<Edge> edgeIterator = vtx.query().labels("Fathered").edges().iterator();
jsonVertexMap.put("HasRelationships", ((Boolean)edgeIterator.hasNext()).toString());
for (String pKey: vtx.getPropertyKeys()) {
jsonVertexMap.put(pKey, vtx.getProperty(pKey).toString());
}
// Add to the Vertex map.
v.put(vtx.getId().toString(), jsonVertexMap);
// Follow this Vertex's edges
while (edgeIterator != null && edgeIterator.hasNext()) {
Edge edge = edgeIterator.next();
String label = edge.getLabel();
Map<String,String> jsonEdgeMap = new HashMap<String,String>();
String tail = edge.getVertex(Direction.OUT).getId().toString();
String head = edge.getVertex(Direction.IN).getId().toString();
jsonEdgeMap.put("tail", tail);
jsonEdgeMap.put("head", head);
jsonEdgeMap.put("label", label);
Direction d = null;
if (tail.equals(vtx.getId().toString())) {
d = Direction.IN;
} else {
d = Direction.OUT;
}
/* If we want an Edge's property keys, uncomment here. Or we can parameterize it.
* Code is here now for reference/memory-jogging.
for (String pKey: edge.getPropertyKeys()) {
jsonEdgeMap.put(pKey, edge.getProperty(pKey).toString());
}
*/
e.put(edge.getId().toString(), jsonEdgeMap);
searchWalker (edge.getVertex(d), max, counter, e, v, edgesToFollow);
}
}
}
/*
* Simple direct graph search and depth traversal.
* @param searchText is plain text
* @param prop is the Vertex property to search.
*/
@Override
public Map<String,HashMap<String,Map<String,String>>> textSearch(String searchText, int depth, String prop) {
HashMap<String,HashMap<String,Map<String,String>>> result = new HashMap<String,HashMap<String,Map<String,String>>>();
// HashMaps, which contain sub JOSN Objects to be relayed back to the parent.
HashMap<String,Map<String,String>> vertices = new HashMap<String,Map<String,String>>();
HashMap<String,Map<String,String>> edges = new HashMap<String,Map<String,String>>();
int resultCount = 0;
for (Vertex v: graphService.getBlueprintsGraph().query().has(prop,searchText).vertices()) {
searchWalker(v, depth, 0, edges, vertices, null);
resultCount++;
}
LOG.debug("Search for {} returned {} results.", searchText ,resultCount);
result.put("vertices", vertices);
result.put("edges",edges);
return result;
}
/*
* Simple graph walker for search interface, which allows following of specific edges only.
* @param edgesToFollow is a comma-separated-list of edges to follow.
*/
@Override
public Map<String,HashMap<String,Map<String,String>>> relationshipWalk(String guid, int depth, String edgesToFollow) {
HashMap<String,HashMap<String,Map<String,String>>> result = new HashMap<String,HashMap<String,Map<String,String>>>();
// HashMaps, which contain sub JOSN Objects to be relayed back to the parent.
HashMap<String,Map<String,String>> vertices = new HashMap<String,Map<String,String>>();
HashMap<String,Map<String,String>> edges = new HashMap<String,Map<String,String>>();
// Get the Vertex with the specified GUID.
Vertex v = GraphHelper.findVertexByGUID(graphService.getBlueprintsGraph(), guid);
if (v != null) {
searchWalker(v, depth, 0, edges, vertices, edgesToFollow);
LOG.debug("Vertex {} found for guid {}", v, guid);
} else {
LOG.debug("Vertex not found for guid {}", guid);
}
result.put("vertices", vertices);
result.put("edges",edges);
return result;
}
/** /**
* Assumes the User is familiar with the persistence structure of the Repository. * Assumes the User is familiar with the persistence structure of the Repository.
* The given query is run uninterpreted against the underlying Graph Store. * The given query is run uninterpreted against the underlying Graph Store.
......
...@@ -18,18 +18,10 @@ ...@@ -18,18 +18,10 @@
package org.apache.hadoop.metadata.web.resources; package org.apache.hadoop.metadata.web.resources;
import org.apache.commons.collections.iterators.IteratorChain;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.tinkerpop.blueprints.Direction;
import com.tinkerpop.blueprints.Edge;
import com.tinkerpop.blueprints.Graph;
import com.tinkerpop.blueprints.Vertex;
import org.apache.hadoop.metadata.MetadataException; import org.apache.hadoop.metadata.MetadataException;
import org.apache.hadoop.metadata.discovery.DiscoveryService; import org.apache.hadoop.metadata.discovery.DiscoveryService;
import org.apache.hadoop.metadata.repository.graph.GraphHelper;
import org.apache.hadoop.metadata.repository.graph.GraphService;
import org.apache.hadoop.metadata.types.TypeSystem; import org.apache.hadoop.metadata.types.TypeSystem;
import org.apache.hadoop.metadata.web.util.Servlets; import org.apache.hadoop.metadata.web.util.Servlets;
import org.codehaus.jettison.json.JSONArray; import org.codehaus.jettison.json.JSONArray;
...@@ -51,10 +43,8 @@ import javax.ws.rs.core.MediaType; ...@@ -51,10 +43,8 @@ import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
/** /**
* Jersey Resource for metadata operations. * Jersey Resource for metadata operations.
...@@ -78,7 +68,6 @@ public class MetadataDiscoveryResource { ...@@ -78,7 +68,6 @@ public class MetadataDiscoveryResource {
public static final List<String> typesList = TypeSystem.getInstance().getTypeNames(); public static final List<String> typesList = TypeSystem.getInstance().getTypeNames();
private final GraphService graphService;
/** /**
* Created by the Guice ServletModule and injected with the * Created by the Guice ServletModule and injected with the
* configured DiscoveryService. * configured DiscoveryService.
...@@ -86,23 +75,10 @@ public class MetadataDiscoveryResource { ...@@ -86,23 +75,10 @@ public class MetadataDiscoveryResource {
* @param discoveryService metadata service handle * @param discoveryService metadata service handle
*/ */
@Inject @Inject
public MetadataDiscoveryResource(GraphService graphService, DiscoveryService discoveryService) { public MetadataDiscoveryResource(DiscoveryService discoveryService) {
this.graphService = graphService;
this.discoveryService = discoveryService; this.discoveryService = discoveryService;
} }
protected Graph getGraph() {
return graphService.getBlueprintsGraph();
}
protected Set<String> getVertexIndexedKeys() {
return graphService.getVertexIndexedKeys();
}
protected Set<String> getEdgeIndexedKeys() {
return graphService.getEdgeIndexedKeys();
}
@GET @GET
@Path("search/gremlin/{gremlinQuery}") @Path("search/gremlin/{gremlinQuery}")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
...@@ -154,25 +130,16 @@ public class MetadataDiscoveryResource { ...@@ -154,25 +130,16 @@ public class MetadataDiscoveryResource {
// Parent JSON Object // Parent JSON Object
JSONObject response = new JSONObject(); JSONObject response = new JSONObject();
Map<String, HashMap<String, Map<String, String>>> resultMap = discoveryService.relationshipWalk(guid, depth, edgesToFollow);
// HashMaps, which contain sub JOSN Objects to be relayed back to the parent.
HashMap<String,Map<String,String>> vertices = new HashMap<String,Map<String,String>>();
HashMap<String,Map<String,String>> edges = new HashMap<String,Map<String,String>>();
// Get the Vertex with the specified GUID.
Vertex v = GraphHelper.findVertexByGUID(getGraph(), guid);
if (v != null) {
searchWalker(v, depth, 0, edges, vertices, edgesToFollow);
LOG.debug("Vertex {} found for guid {}", v, guid);
} else {
LOG.debug("Vertex not found for guid {}", guid);
}
try { try {
response.put("requestId", Thread.currentThread().getName()); response.put("requestId", Thread.currentThread().getName());
response.put("vertices",vertices); if (resultMap.containsKey("vertices")) {
response.put("edges",edges); response.put("vertices",resultMap.get("vertices"));
}
if (resultMap.containsKey("edges")) {
response.put("edges",resultMap.get("edges"));
}
} catch (JSONException e) { } catch (JSONException e) {
throw new WebApplicationException( throw new WebApplicationException(
Servlets.getErrorResponse("Search: Error building JSON result set.", Response.Status.INTERNAL_SERVER_ERROR)); Servlets.getErrorResponse("Search: Error building JSON result set.", Response.Status.INTERNAL_SERVER_ERROR));
...@@ -196,7 +163,7 @@ public class MetadataDiscoveryResource { ...@@ -196,7 +163,7 @@ public class MetadataDiscoveryResource {
public Response getFullTextResults(@QueryParam("text") final String searchText, public Response getFullTextResults(@QueryParam("text") final String searchText,
@DefaultValue("1") @QueryParam("depth") final int depth, @QueryParam("property") final String prop) { @DefaultValue("1") @QueryParam("depth") final int depth, @QueryParam("property") final String prop) {
LOG.info("Performing full text search for vertices matching= {}", searchText); LOG.info("Performing full text search for vertices with property {} matching= {}", prop, searchText);
Preconditions.checkNotNull(searchText, "Invalid argument: \"text\" cannot be null."); Preconditions.checkNotNull(searchText, "Invalid argument: \"text\" cannot be null.");
Preconditions.checkNotNull(prop, "Invalid argument: \"prop\" cannot be null."); Preconditions.checkNotNull(prop, "Invalid argument: \"prop\" cannot be null.");
...@@ -216,24 +183,16 @@ public class MetadataDiscoveryResource { ...@@ -216,24 +183,16 @@ public class MetadataDiscoveryResource {
// Parent JSON Object // Parent JSON Object
JSONObject response = new JSONObject(); JSONObject response = new JSONObject();
// HashMaps, which contain sub JOSN Objects to be relayed back to the parent. Map<String, HashMap<String, Map<String, String>>> resultMap = discoveryService.textSearch(searchText, depth, prop);
HashMap<String,Map<String,String>> vertices = new HashMap<String,Map<String,String>>();
HashMap<String,Map<String,String>> edges = new HashMap<String,Map<String,String>>();
int resultCount = 0;
for (Vertex v: getGraph().query().has(prop,searchText).vertices()) {
searchWalker(v, depth, 0, edges, vertices, null);
resultCount++;
}
LOG.debug("Search for {} returned {} results.", searchText ,resultCount);
try { try {
response.put("requestId", Thread.currentThread().getName()); response.put("requestId", Thread.currentThread().getName());
response.put("vertices",vertices); if (resultMap.containsKey("vertices")) {
response.put("edges",edges); response.put("vertices",resultMap.get("vertices"));
}
if (resultMap.containsKey("edges")) {
response.put("edges",resultMap.get("edges"));
}
} catch (JSONException e) { } catch (JSONException e) {
throw new WebApplicationException( throw new WebApplicationException(
Servlets.getErrorResponse("Search: Error building JSON result set.", Response.Status.INTERNAL_SERVER_ERROR)); Servlets.getErrorResponse("Search: Error building JSON result set.", Response.Status.INTERNAL_SERVER_ERROR));
...@@ -244,77 +203,4 @@ public class MetadataDiscoveryResource { ...@@ -244,77 +203,4 @@ public class MetadataDiscoveryResource {
} }
private static void searchWalker (Vertex vtx, final int max, int counter, HashMap<String,Map<String,String>> e, HashMap<String,Map<String,String>> v, String edgesToFollow) {
counter++;
if (counter <= max) {
Map<String,String> jsonVertexMap = new HashMap<String,String>();
Iterator<Edge> edgeIterator = null;
// If we're doing a lineage traversal, only follow the edges specified by the query. Otherwise
// return them all.
if (edgesToFollow != null) {
IteratorChain ic = new IteratorChain();
for (String iterateOn: edgesToFollow.split(",")){
ic.addIterator(vtx.query().labels(iterateOn).edges().iterator());
}
edgeIterator = ic;
} else {
edgeIterator = vtx.query().edges().iterator();
}
//Iterator<Edge> edgeIterator = vtx.query().labels("Fathered").edges().iterator();
jsonVertexMap.put("HasRelationships", ((Boolean)edgeIterator.hasNext()).toString());
for (String pKey: vtx.getPropertyKeys()) {
jsonVertexMap.put(pKey, vtx.getProperty(pKey).toString());
}
// Add to the Vertex map.
v.put(vtx.getId().toString(), jsonVertexMap);
// Follow this Vertex's edges
while (edgeIterator != null && edgeIterator.hasNext()) {
Edge edge = edgeIterator.next();
String label = edge.getLabel();
Map<String,String> jsonEdgeMap = new HashMap<String,String>();
String tail = edge.getVertex(Direction.OUT).getId().toString();
String head = edge.getVertex(Direction.IN).getId().toString();
jsonEdgeMap.put("tail", tail);
jsonEdgeMap.put("head", head);
jsonEdgeMap.put("label", label);
Direction d = null;
if (tail.equals(vtx.getId().toString())) {
d = Direction.IN;
} else {
d = Direction.OUT;
}
/* If we want an Edge's property keys, uncomment here. Or we can parameterize it.
* Code is here now for reference/memory-jogging.
for (String pKey: edge.getPropertyKeys()) {
jsonEdgeMap.put(pKey, edge.getProperty(pKey).toString());
}
*/
e.put(edge.getId().toString(), jsonEdgeMap);
searchWalker (edge.getVertex(d), max, counter, e, v, edgesToFollow);
}
}
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment