All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.jena.query.text.TextIndexSolr Maven / Gradle / Ivy

There is a newer version: 5.2.0
Show newest version
/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.jena.query.text;

import java.io.IOException ;
import java.util.ArrayList ;
import java.util.HashMap ;
import java.util.List ;
import java.util.Map ;
import java.util.Map.Entry ;

import org.apache.jena.graph.Node ;
import org.apache.jena.graph.NodeFactory ;
import org.apache.jena.sparql.util.NodeFactoryExtra ;
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.util.ClientUtils ;
import org.apache.solr.common.SolrDocument ;
import org.apache.solr.common.SolrDocumentList ;
import org.apache.solr.common.SolrInputDocument ;
import org.apache.solr.common.params.CommonParams ;
import org.slf4j.Logger ;
import org.slf4j.LoggerFactory ;

public class TextIndexSolr implements TextIndex
{
    private static final Logger log = LoggerFactory.getLogger(TextIndexSolr.class) ;
    private final SolrServer solrServer ;
    private final EntityDefinition docDef ;
    private static final int MAX_N    = 10000 ;

    public TextIndexSolr(SolrServer server, EntityDefinition def) {
        this.solrServer = server ;
        this.docDef = def ;
    }

    @Override
    public void updateEntity(Entity entity) {
        throw new RuntimeException("TextIndexSolr.updateEntity not implemented.") ;
    }

    @Override
    public void prepareCommit() {}

    @Override
    public void commit() {
        try {
            solrServer.commit() ;
        }
        catch (SolrServerException e) {
            throw new TextIndexException(e) ;
        }
        catch (IOException e) {
            throw new TextIndexException(e) ;
        }
    }

    @Override
    public void rollback() {
        try {
            solrServer.rollback() ;
        }
        catch (SolrServerException e) {
            throw new TextIndexException(e) ;
        }
        catch (IOException e) {
            throw new TextIndexException(e) ;
        }
    }

    @Override
    public void close() {
        if ( solrServer != null )
            solrServer.shutdown() ;
    }

    @Override
    public void addEntity(Entity entity) {
        // log.info("Add entity: "+entity) ;
        try {
            SolrInputDocument doc = solrDoc(entity) ;
            solrServer.add(doc) ;
        }
        catch (Exception e) {
            exception(e) ;
        }
    }

    @Override
    public void deleteEntity(Entity entity) {
         //to be implemented
    }

    private SolrInputDocument solrDoc(Entity entity)
    {
        SolrInputDocument doc = new SolrInputDocument() ;
        doc.addField(docDef.getEntityField(), entity.getId()) ;

        String graphField = docDef.getGraphField() ;
        if ( graphField != null ) {
            doc.addField(graphField, entity.getGraph()) ;
        }

        // the addition needs to be done as a partial update
        // otherwise, if we have multiple fields, each successive
        // addition will replace the previous one and we are left
        // with only the last field indexed.
        // see
        // http://stackoverflow.com/questions/12183798/solrj-api-for-partial-document-update
        // and
        // https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleTests.java
        HashMap map = new HashMap<>() ;
        for ( Entry e : entity.getMap().entrySet() ) {
            map.put("add", e.getValue()) ;
            doc.addField(e.getKey(), map) ;
        }
        return doc ;
    }

    @Override
    public Map get(String uri) {
        String escaped = ClientUtils.escapeQueryChars(uri) ;
        String qs = docDef.getEntityField() + ":" + escaped ;
        SolrDocumentList solrResults = solrQuery(qs, 1) ;

        List> records = process(solrResults) ;
        if ( records.size() == 0 )
            return null ;
        if ( records.size() > 1 )
            log.warn("Multiple docs for one URI: " + uri) ;
        return records.get(0) ;
    }

    private List> process(SolrDocumentList solrResults) {
        List> records = new ArrayList<>() ;

        for ( SolrDocument sd : solrResults ) {
            Map record = new HashMap<>() ;
            String uriStr = (String)sd.getFieldValue(docDef.getEntityField()) ;
            Node entity = NodeFactory.createURI(uriStr) ;
            record.put(docDef.getEntityField(), entity) ;

            for ( String f : docDef.fields() ) {
                // log.info("Field: "+f) ;
                Object obj = sd.getFieldValue(f) ;
                // log.info("Value: "+obj) ;
                if ( obj == null )
                    continue ;
                // Multivalued -> array.
                // Null means "not stored" or "not present"
                if ( obj instanceof List ) 
                    continue ;

                String v = (String)obj ;
                Node n = entryToNode(v) ;
                record.put(f, n) ;
            }

            // log.info("Entity: "+uriStr) ;
            records.add(record) ;
        }
        return records ;
    }

    @Override
    public List query(Node property, String qs) { return query(property, qs, 0) ; }

    @Override
    public List query(Node property, String qs, int limit) {
        SolrDocumentList solrResults = solrQuery(qs, limit) ;
        List results = new ArrayList<>() ;

        for ( SolrDocument sd : solrResults ) {
            String str = (String)sd.getFieldValue(docDef.getEntityField()) ;
            // log.info("Entity: "+uriStr) ;
            Node n = TextQueryFuncs.stringToNode(str) ;
            Float score = (Float) sd.getFirstValue("score");
            // capture literal value, if stored
            Node literal = null;
            String field = (property != null) ? docDef.getField(property) : docDef.getPrimaryField();
            String value = (String) sd.getFirstValue(field);
            if (value != null) {
                literal = NodeFactory.createLiteral(value); // FIXME: language and datatype
            }
            TextHit hit = new TextHit(n, score.floatValue(), literal);
            results.add(hit) ;
        }

        if ( limit > 0 && results.size() > limit )
            results = results.subList(0, limit) ;

        return results ;
    }

    private SolrDocumentList solrQuery(String qs, int limit) {
        SolrQuery sq = new SolrQuery(qs) ;
        sq.setIncludeScore(true) ;
        if ( limit > 0 )
            sq.setRows(limit) ;
        else
            sq.setRows(MAX_N) ; // The Solr default is 10.
        try {
            // Set default field.
            sq.add(CommonParams.DF, docDef.getPrimaryField()) ;
            QueryResponse rsp = solrServer.query(sq) ;
            SolrDocumentList docs = rsp.getResults() ;
            return docs ;
        }
        catch (SolrServerException e) {
            exception(e) ;
            return null ;
        }
    }

    @Override
    public EntityDefinition getDocDef() {
        return docDef ;
    }

    private Node entryToNode(String v) {
        // TEMP
        return NodeFactoryExtra.createLiteralNode(v, null, null) ;
    }

    public SolrServer getServer() {
        return solrServer ;
    }

    private static Void exception(Exception ex) {
        throw new TextIndexException(ex) ;
    }
}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy