Skip to content

Commit

Permalink
[ issue #14 ] first draft SOLR binding module
Browse files Browse the repository at this point in the history
  • Loading branch information
agazzarini committed Aug 25, 2014
1 parent 8900ada commit cfdf846
Show file tree
Hide file tree
Showing 16 changed files with 475 additions and 42 deletions.
5 changes: 0 additions & 5 deletions jena-nosql-binding/jena-nosql-binding-cassandra/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,6 @@
<artifactId>jena-nosql-binding-cassandra</artifactId>
<name>Jena Cassandra binding implementation.</name>
<dependencies>
<dependency>
<groupId>org.gazzax.labs</groupId>
<artifactId>jena-nosql-framework</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>com.datastax.cassandra</groupId>
<artifactId>cassandra-driver-core</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,7 @@
import org.gazzax.labs.jena.nosql.fwk.InitialisationException;
import org.gazzax.labs.jena.nosql.fwk.configuration.Configuration;
import org.gazzax.labs.jena.nosql.fwk.dictionary.TopLevelDictionary;
import org.gazzax.labs.jena.nosql.fwk.dictionary.node.CacheNodectionary;
import org.gazzax.labs.jena.nosql.fwk.dictionary.node.KnownURIsDictionary;
import org.gazzax.labs.jena.nosql.fwk.dictionary.node.PersistentNodeDictionary;
import org.gazzax.labs.jena.nosql.fwk.dictionary.node.ThreeTieredNodeDictionary;
import org.gazzax.labs.jena.nosql.fwk.dictionary.node.TransientNodeDictionary;
import org.gazzax.labs.jena.nosql.fwk.dictionary.string.CacheStringDictionary;
import org.gazzax.labs.jena.nosql.fwk.dictionary.string.PersistentStringDictionary;
import org.gazzax.labs.jena.nosql.fwk.dictionary.string.TransientStringDictionary;
import org.gazzax.labs.jena.nosql.fwk.ds.MapDAO;
import org.gazzax.labs.jena.nosql.fwk.ds.TripleIndexDAO;
import org.gazzax.labs.jena.nosql.fwk.factory.ClientShutdownHook;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
* @author Andrea Gazzarini
* @since 1.0
*/
public class CassandraTripleIndexDAO implements TripleIndexDAO<byte[][]> {
public class CassandraTripleIndexDAO implements TripleIndexDAO<byte[][], byte[][]> {
protected static final byte[] EMPTY_VAL = new byte[0];
protected static final String SELECT_SPOC_FROM = "SELECT s, p, o, c FROM ";

Expand Down
24 changes: 24 additions & 0 deletions jena-nosql-binding/jena-nosql-binding-solr/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>jena-nosql-binding</artifactId>
<groupId>org.gazzax.labs</groupId>
<version>1.0</version>
<relativePath>..</relativePath>
</parent>
<artifactId>jena-nosql-binding-solr</artifactId>
<name>Apache SOLR binding module</name>
<description>https://github.com/agazzarini/jena-nosql/issues/14</description>
<properties>
<solr.version>4.8.0</solr.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-solrj</artifactId>
<version>${solr.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.gazzax.labs.jena.nosql.solr;

public interface Field {
String S = "s";
String P = "p";
String O = "o";
String C = "c";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package org.gazzax.labs.jena.nosql.solr;

import java.util.Map;

import org.apache.solr.client.solrj.SolrServer;
import org.gazzax.labs.jena.nosql.fwk.configuration.Configuration;
import org.gazzax.labs.jena.nosql.fwk.dictionary.TopLevelDictionary;
import org.gazzax.labs.jena.nosql.fwk.ds.MapDAO;
import org.gazzax.labs.jena.nosql.fwk.ds.TripleIndexDAO;
import org.gazzax.labs.jena.nosql.fwk.factory.ClientShutdownHook;
import org.gazzax.labs.jena.nosql.fwk.factory.StorageLayerFactory;
import org.gazzax.labs.jena.nosql.fwk.graph.NoSqlGraph;
import org.gazzax.labs.jena.nosql.solr.dao.SolrTripleIndexDAO;
import org.gazzax.labs.jena.nosql.solr.graph.SolrGraph;

import com.hp.hpl.jena.graph.Graph;
import com.hp.hpl.jena.graph.Node;

/**
* Concrete factory for creating SOLR-based domain and data access objects.
*
* @author Andrea Gazzarini
* @since 1.0
*/
public class SolrStorageLayerFactory extends StorageLayerFactory {
private SolrServer solr;

@Override
public void accept(final Configuration<Map<String, Object>> configuration) {
// TODO Auto-generated method stub
}

@Override
public <K, V> MapDAO<K, V> getMapDAO(
final Class<K> keyClass,
final Class<V> valueClass,
final boolean isBidirectional,
final String name) {
return null;
}

@Override
public Graph getGraph() {
return new SolrGraph(this);
}

@Override
public Graph getGraph(Node graphNode) {
return new SolrGraph(graphNode, this);
}

@Override
public TripleIndexDAO getTripleIndexDAO() {
return new SolrTripleIndexDAO(solr);
}

@Override
public TopLevelDictionary getDictionary() {
return null;
}

@Override
public ClientShutdownHook getClientShutdownHook() {
return null;
}

@Override
public String getInfo() {
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
package org.gazzax.labs.jena.nosql.solr.dao;

import static org.gazzax.labs.jena.nosql.fwk.util.NTriples.asNt;
import static org.gazzax.labs.jena.nosql.fwk.util.NTriples.asNtURI;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.client.solrj.response.UpdateResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrInputDocument;
import org.gazzax.labs.jena.nosql.fwk.StorageLayerException;
import org.gazzax.labs.jena.nosql.fwk.ds.TripleIndexDAO;
import org.gazzax.labs.jena.nosql.fwk.util.NTriples;
import org.gazzax.labs.jena.nosql.solr.Field;

import com.google.common.collect.AbstractIterator;
import com.hp.hpl.jena.graph.Node;
import com.hp.hpl.jena.graph.Triple;
import com.hp.hpl.jena.graph.TripleMatch;

public class SolrTripleIndexDAO implements TripleIndexDAO<Triple, TripleMatch> {

private final static Iterator<Triple> EMPTY_TRIPLES_ITERATOR = new ArrayList<Triple>(0).iterator();

private final SolrServer solr;

/**
* Builds a new {@link TripleIndexDAO} with the given SOLR client.
*
* @param solr the SOLR client.
*/
public SolrTripleIndexDAO(final SolrServer solr) {
this.solr = solr;
}

@Override
public void insertTriple(final Triple triple) throws StorageLayerException {
final SolrInputDocument document = new SolrInputDocument();
document.setField(Field.S, asNt(triple.getSubject()));
document.setField(Field.P, asNtURI(triple.getPredicate()));
document.setField(Field.O, asNt(triple.getSubject()));

try {
solr.add(document);
} catch (final Exception exception) {
throw new StorageLayerException(exception);
}
}

@Override
public void deleteTriple(final Triple triple) throws StorageLayerException {
try {
solr.deleteByQuery(deleteQuery(triple));
} catch (final Exception exception) {
throw new StorageLayerException(exception);
}
}

/**
* Builds a delete query starting from a given triple.
*
* @param triple the triple.
* @return a delete query starting from a given triple.
*/
private String deleteQuery(final Triple triple) {
return new StringBuilder()
.append(Field.S).append(":\"").append(asNt(triple.getSubject())).append("\" AND ")
.append(Field.P).append(":\"").append(asNt(triple.getPredicate())).append("\" AND ")
.append(Field.O).append(":\"").append(asNt(triple.getObject())).append("\"")
.toString();
}

// TODO: To be optimized...with this implementation wildcard queries are not supported
// so if I need to delete 5 triples then 5 commands should be issued.
@Override
public List<Triple> deleteTriples(
final Iterator<Triple> triples,
final int batchSize) throws StorageLayerException {
final List<Triple> result = new ArrayList<Triple>();
while (triples.hasNext()) {
final Triple triple = triples.next();
try {
final UpdateResponse response = solr.deleteByQuery(deleteQuery(triple));
if (response.getStatus() == 0) {
result.add(triple);
}
} catch (final Exception exception) {
throw new StorageLayerException(exception);
}
}

return null;
}

@Override
public void executePendingMutations() throws StorageLayerException {
try {
solr.commit();
} catch (final Exception exception) {
throw new StorageLayerException(exception);
}
}

@Override
public void clear() {
try {
solr.deleteByQuery("*;*");
} catch (final Exception exception) {
// TODO: log
exception.printStackTrace();
}
}

@Override
public Iterator<Triple> query(final TripleMatch query) throws StorageLayerException {
final SolrQuery q = new SolrQuery("*:*");
q.setStart(0);
final Node s = query.getMatchSubject();
final Node p = query.getMatchPredicate();
final Node o = query.getMatchObject();

if (s != null) {
q.addFilterQuery(
new StringBuilder()
.append(Field.S)
.append(":\"")
.append(asNt(s))
.append("\"")
.toString());
}

if (p != null) {
q.addFilterQuery(
new StringBuilder()
.append(Field.P)
.append(":\"")
.append(asNtURI(p))
.append("\"")
.toString());
}

if (o != null) {
q.addFilterQuery(
new StringBuilder()
.append(Field.O)
.append(":\"")
.append(asNt(o))
.append("\"")
.toString());
}

try {
final QueryResponse response = solr.query(q);

if (response.getResults().getNumFound() == 0) {
return EMPTY_TRIPLES_ITERATOR;
}

return new AbstractIterator<Triple>() {

int rowId;
SolrDocumentList page = response.getResults();

@Override
protected Triple computeNext() {

if (page.getStart() + page.size() == page.getNumFound()) {
return endOfData();
}

if (rowId == page.size() - 1) {
rowId = 0;
q.setStart(q.getStart() + page.size());
try {
page = solr.query(q).getResults();
} catch (final SolrServerException exception) {
throw new RuntimeException(exception);
}
}

final SolrDocument document = page.get(rowId);
return Triple.create(
NTriples.asURIorBlankNode((String) document.getFieldValue(Field.S)),
NTriples.asURI((String) document.getFieldValue(Field.P)),
NTriples.asNode((String) document.getFieldValue(Field.P)));
}
};
} catch (final Exception exception) {
throw new StorageLayerException(exception);
}
}
}
Loading

0 comments on commit cfdf846

Please sign in to comment.