package dgm.modules.elasticsearch;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.inject.Inject;
import com.tinkerpop.blueprints.Edge;
import com.tinkerpop.blueprints.Vertex;
import dgm.GraphUtilities;
import dgm.ID;
import dgm.trees.Pair;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.client.Client;
import org.nnsoft.guice.sli4j.core.InjectLogger;
import org.slf4j.Logger;
/**
* Retrieve document from elasticsearch, based on Vertex
*
* TODO caching
* TODO query priorities
*
* @author wires
*/
public class QueryFunction implements Function<Pair<Edge,Vertex>, Optional<ResolvedPathElement>>
{
@InjectLogger
protected Logger log;
protected final Client searchIndex;
protected final ObjectMapper objectMapper;
@Inject
public QueryFunction(Client searchIndex, ObjectMapper objectMapper)
{
this.searchIndex = searchIndex;
this.objectMapper = objectMapper;
}
@Override
public final Optional<ResolvedPathElement> apply(final Pair<Edge,Vertex> pair)
{
// dump information on the current vertex
if (log.isTraceEnabled())
{
log.trace("Retrieving document from ES for vertex {}", pair.b);
for (String key : pair.b.getPropertyKeys())
log.trace("Property {} has value '{}'", key, pair.b.getProperty(key));
}
// retrieve id property
final ID id = GraphUtilities.getID(objectMapper, pair.b);
// vertices without ID's cannot be looked up
if(id == null)
{
log.debug("Vertex has no ID assigned, properties are: ");
for (String key : pair.b.getPropertyKeys())
log.debug("Property {} has value '{}'", key, pair.b.getProperty(key));
return Optional.of(new ResolvedPathElement(Optional.<GetResponse>absent(), pair.a, pair.b));
}
// this document should not exist in elastic search, otherwise the vertex would have a version > 0
if(id.version() == 0)
{
log.debug("Document {} is symbolic, so we won't attempt to find it in elasticsearch", id);
return Optional.of(new ResolvedPathElement(Optional.<GetResponse>absent(), pair.a, pair.b));
}
// query ES for the document
final GetResponse r = searchIndex.prepareGet(id.index(), id.type(), id.id())
.execute().actionGet();
if ((r.version() == -1) || !r.exists())
{
log.debug("Document {} does not exist!", id);
return Optional.of(new ResolvedPathElement(Optional.<GetResponse>absent(), pair.a, pair.b));
}
// query has expired in the meantime
if (r.version() != id.version())
{
log.warn("Document {} expired, version in ES is {}!", id, r.version());
return Optional.absent();
}
return Optional.of(new ResolvedPathElement(Optional.of(r), pair.a, pair.b));
}
}