Search in sources :

Example 1 with SolrIndexSearcher

use of org.apache.solr.search.SolrIndexSearcher in project lucene-solr by apache.

the class TestHierarchicalDocBuilder method assertSearch.

private void assertSearch(Query query, String field, String... values) throws IOException {
    /* The limit of search queue is doubled to catch the error in case when for some reason there are more docs than expected  */
    SolrIndexSearcher searcher = req.getSearcher();
    TopDocs result = searcher.search(query, values.length * 2);
    assertEquals(values.length, result.totalHits);
    List<String> actualValues = new ArrayList<String>();
    for (int index = 0; index < values.length; ++index) {
        Document doc = searcher.doc(result.scoreDocs[index].doc);
        actualValues.add(doc.get(field));
    }
    for (String expectedValue : values) {
        boolean removed = actualValues.remove(expectedValue);
        if (!removed) {
            fail("Search result does not contain expected values");
        }
    }
}
Also used : TopDocs(org.apache.lucene.search.TopDocs) ArrayList(java.util.ArrayList) SolrIndexSearcher(org.apache.solr.search.SolrIndexSearcher) Document(org.apache.lucene.document.Document)

Example 2 with SolrIndexSearcher

use of org.apache.solr.search.SolrIndexSearcher in project lucene-solr by apache.

the class SolrCore method getSearcher.

/**
   * Get a {@link SolrIndexSearcher} or start the process of creating a new one.
   * <p>
   * The registered searcher is the default searcher used to service queries.
   * A searcher will normally be registered after all of the warming
   * and event handlers (newSearcher or firstSearcher events) have run.
   * In the case where there is no registered searcher, the newly created searcher will
   * be registered before running the event handlers (a slow searcher is better than no searcher).
   *
   * <p>
   * These searchers contain read-only IndexReaders. To access a non read-only IndexReader,
   * see newSearcher(String name, boolean readOnly).
   *
   * <p>
   * If <tt>forceNew==true</tt> then
   *  A new searcher will be opened and registered regardless of whether there is already
   *    a registered searcher or other searchers in the process of being created.
   * <p>
   * If <tt>forceNew==false</tt> then:<ul>
   *   <li>If a searcher is already registered, that searcher will be returned</li>
   *   <li>If no searcher is currently registered, but at least one is in the process of being created, then
   * this call will block until the first searcher is registered</li>
   *   <li>If no searcher is currently registered, and no searchers in the process of being registered, a new
   * searcher will be created.</li>
   * </ul>
   * <p>
   * If <tt>returnSearcher==true</tt> then a {@link RefCounted}&lt;{@link SolrIndexSearcher}&gt; will be returned with
   * the reference count incremented.  It <b>must</b> be decremented when no longer needed.
   * <p>
   * If <tt>waitSearcher!=null</tt> and a new {@link SolrIndexSearcher} was created,
   * then it is filled in with a Future that will return after the searcher is registered.  The Future may be set to
   * <tt>null</tt> in which case the SolrIndexSearcher created has already been registered at the time
   * this method returned.
   * <p>
   * @param forceNew             if true, force the open of a new index searcher regardless if there is already one open.
   * @param returnSearcher       if true, returns a {@link SolrIndexSearcher} holder with the refcount already incremented.
   * @param waitSearcher         if non-null, will be filled in with a {@link Future} that will return after the new searcher is registered.
   * @param updateHandlerReopens if true, the UpdateHandler will be used when reopening a {@link SolrIndexSearcher}.
   */
public RefCounted<SolrIndexSearcher> getSearcher(boolean forceNew, boolean returnSearcher, final Future[] waitSearcher, boolean updateHandlerReopens) {
    synchronized (searcherLock) {
        for (; ; ) {
            // see if we can return the current searcher
            if (_searcher != null && !forceNew) {
                if (returnSearcher) {
                    _searcher.incref();
                    return _searcher;
                } else {
                    return null;
                }
            }
            // check to see if we can wait for someone else's searcher to be set
            if (onDeckSearchers > 0 && !forceNew && _searcher == null) {
                try {
                    searcherLock.wait();
                } catch (InterruptedException e) {
                    log.info(SolrException.toStr(e));
                }
            }
            // check again: see if we can return right now
            if (_searcher != null && !forceNew) {
                if (returnSearcher) {
                    _searcher.incref();
                    return _searcher;
                } else {
                    return null;
                }
            }
            // At this point, we know we need to open a new searcher...
            // first: increment count to signal other threads that we are
            //        opening a new searcher.
            onDeckSearchers++;
            newSearcherCounter.inc();
            if (onDeckSearchers < 1) {
                // should never happen... just a sanity check
                log.error(logid + "ERROR!!! onDeckSearchers is " + onDeckSearchers);
                // reset
                onDeckSearchers = 1;
            } else if (onDeckSearchers > maxWarmingSearchers) {
                onDeckSearchers--;
                newSearcherMaxReachedCounter.inc();
                try {
                    searcherLock.wait();
                } catch (InterruptedException e) {
                    log.info(SolrException.toStr(e));
                }
                // go back to the top of the loop and retry
                continue;
            } else if (onDeckSearchers > 1) {
                log.warn(logid + "PERFORMANCE WARNING: Overlapping onDeckSearchers=" + onDeckSearchers);
            }
            // I can now exit the loop and proceed to open a searcher
            break;
        }
    }
    // a signal to decrement onDeckSearchers if something goes wrong.
    final boolean[] decrementOnDeckCount = new boolean[] { true };
    // searcher we are autowarming from
    RefCounted<SolrIndexSearcher> currSearcherHolder = null;
    RefCounted<SolrIndexSearcher> searchHolder = null;
    boolean success = false;
    openSearcherLock.lock();
    Timer.Context timerContext = newSearcherTimer.time();
    try {
        searchHolder = openNewSearcher(updateHandlerReopens, false);
        // increment it again if we are going to return it to the caller.
        if (returnSearcher) {
            searchHolder.incref();
        }
        final RefCounted<SolrIndexSearcher> newSearchHolder = searchHolder;
        final SolrIndexSearcher newSearcher = newSearchHolder.get();
        boolean alreadyRegistered = false;
        synchronized (searcherLock) {
            if (_searcher == null) {
                // want to register this one before warming is complete instead of waiting.
                if (solrConfig.useColdSearcher) {
                    registerSearcher(newSearchHolder);
                    decrementOnDeckCount[0] = false;
                    alreadyRegistered = true;
                }
            } else {
                // get a reference to the current searcher for purposes of autowarming.
                currSearcherHolder = _searcher;
                currSearcherHolder.incref();
            }
        }
        final SolrIndexSearcher currSearcher = currSearcherHolder == null ? null : currSearcherHolder.get();
        Future future = null;
        // if the underlying searcher has not changed, no warming is needed
        if (newSearcher != currSearcher) {
            // should this go before the other event handlers or after?
            if (currSearcher != null) {
                future = searcherExecutor.submit(() -> {
                    Timer.Context warmupContext = newSearcherWarmupTimer.time();
                    try {
                        newSearcher.warm(currSearcher);
                    } catch (Throwable e) {
                        SolrException.log(log, e);
                        if (e instanceof Error) {
                            throw (Error) e;
                        }
                    } finally {
                        warmupContext.close();
                    }
                    return null;
                });
            }
            if (currSearcher == null) {
                future = searcherExecutor.submit(() -> {
                    try {
                        for (SolrEventListener listener : firstSearcherListeners) {
                            listener.newSearcher(newSearcher, null);
                        }
                    } catch (Throwable e) {
                        SolrException.log(log, null, e);
                        if (e instanceof Error) {
                            throw (Error) e;
                        }
                    }
                    return null;
                });
            }
            if (currSearcher != null) {
                future = searcherExecutor.submit(() -> {
                    try {
                        for (SolrEventListener listener : newSearcherListeners) {
                            listener.newSearcher(newSearcher, currSearcher);
                        }
                    } catch (Throwable e) {
                        SolrException.log(log, null, e);
                        if (e instanceof Error) {
                            throw (Error) e;
                        }
                    }
                    return null;
                });
            }
        }
        // WARNING: this code assumes a single threaded executor (that all tasks
        // queued will finish first).
        final RefCounted<SolrIndexSearcher> currSearcherHolderF = currSearcherHolder;
        if (!alreadyRegistered) {
            future = searcherExecutor.submit(() -> {
                try {
                    // registerSearcher will decrement onDeckSearchers and
                    // do a notify, even if it fails.
                    registerSearcher(newSearchHolder);
                } catch (Throwable e) {
                    SolrException.log(log, e);
                    if (e instanceof Error) {
                        throw (Error) e;
                    }
                } finally {
                    // for warming...
                    if (currSearcherHolderF != null)
                        currSearcherHolderF.decref();
                }
                return null;
            });
        }
        if (waitSearcher != null) {
            waitSearcher[0] = future;
        }
        success = true;
        // callers may wait on the waitSearcher future returned.
        return returnSearcher ? newSearchHolder : null;
    } catch (Exception e) {
        if (e instanceof SolrException)
            throw (SolrException) e;
        throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, e);
    } finally {
        timerContext.close();
        if (!success) {
            newSearcherOtherErrorsCounter.inc();
            ;
            synchronized (searcherLock) {
                onDeckSearchers--;
                if (onDeckSearchers < 0) {
                    // sanity check... should never happen
                    log.error(logid + "ERROR!!! onDeckSearchers after decrement=" + onDeckSearchers);
                    // try and recover
                    onDeckSearchers = 0;
                }
                // if we failed, we need to wake up at least one waiter to continue the process
                searcherLock.notify();
            }
            if (currSearcherHolder != null) {
                currSearcherHolder.decref();
            }
            if (searchHolder != null) {
                // decrement 1 for _searcher (searchHolder will never become _searcher now)
                searchHolder.decref();
                if (returnSearcher) {
                    // decrement 1 because we won't be returning the searcher to the user
                    searchHolder.decref();
                }
            }
        }
        // we want to do this after we decrement onDeckSearchers so another thread
        // doesn't increment first and throw a false warning.
        openSearcherLock.unlock();
    }
}
Also used : IOContext(org.apache.lucene.store.IOContext) MDCLoggingContext(org.apache.solr.logging.MDCLoggingContext) DirContext(org.apache.solr.core.DirectoryFactory.DirContext) LeafReaderContext(org.apache.lucene.index.LeafReaderContext) SolrIndexSearcher(org.apache.solr.search.SolrIndexSearcher) LockObtainFailedException(org.apache.lucene.store.LockObtainFailedException) IOException(java.io.IOException) NoSuchFileException(java.nio.file.NoSuchFileException) SolrException(org.apache.solr.common.SolrException) FileNotFoundException(java.io.FileNotFoundException) KeeperException(org.apache.zookeeper.KeeperException) Timer(com.codahale.metrics.Timer) Future(java.util.concurrent.Future) SolrException(org.apache.solr.common.SolrException)

Example 3 with SolrIndexSearcher

use of org.apache.solr.search.SolrIndexSearcher in project lucene-solr by apache.

the class SolrCore method registerSearcher.

// Take control of newSearcherHolder (which should have a reference count of at
// least 1 already.  If the caller wishes to use the newSearcherHolder directly
// after registering it, then they should increment the reference count *before*
// calling this method.
//
// onDeckSearchers will also be decremented (it should have been incremented
// as a result of opening a new searcher).
private void registerSearcher(RefCounted<SolrIndexSearcher> newSearcherHolder) {
    synchronized (searcherLock) {
        try {
            if (_searcher == newSearcherHolder) {
                // trying to re-register the same searcher... this can now happen when a commit has been done but
                // there were no changes to the index.
                // decref since the caller should have still incref'd (since they didn't know the searcher was the same)
                newSearcherHolder.decref();
                // still execute the finally block to notify anyone waiting.
                return;
            }
            if (_searcher != null) {
                // dec refcount for this._searcher
                _searcher.decref();
                _searcher = null;
            }
            _searcher = newSearcherHolder;
            SolrIndexSearcher newSearcher = newSearcherHolder.get();
            /***
        // a searcher may have been warming asynchronously while the core was being closed.
        // if this happens, just close the searcher.
        if (isClosed()) {
          // NOTE: this should not happen now - see close() for details.
          // *BUT* if we left it enabled, this could still happen before
          // close() stopped the executor - so disable this test for now.
          log.error("Ignoring searcher register on closed core:" + newSearcher);
          _searcher.decref();
        }
        ***/
            // register subitems (caches)
            newSearcher.register();
            log.info(logid + "Registered new searcher " + newSearcher);
        } catch (Exception e) {
            // an exception in register() shouldn't be fatal.
            log(e);
        } finally {
            // wake up anyone waiting for a searcher
            // even in the face of errors.
            onDeckSearchers--;
            searcherLock.notifyAll();
        }
    }
}
Also used : SolrIndexSearcher(org.apache.solr.search.SolrIndexSearcher) LockObtainFailedException(org.apache.lucene.store.LockObtainFailedException) IOException(java.io.IOException) NoSuchFileException(java.nio.file.NoSuchFileException) SolrException(org.apache.solr.common.SolrException) FileNotFoundException(java.io.FileNotFoundException) KeeperException(org.apache.zookeeper.KeeperException)

Example 4 with SolrIndexSearcher

use of org.apache.solr.search.SolrIndexSearcher in project lucene-solr by apache.

the class QueryComponent method prepareGrouping.

protected void prepareGrouping(ResponseBuilder rb) throws IOException {
    SolrQueryRequest req = rb.req;
    SolrParams params = req.getParams();
    if (null != rb.getCursorMark()) {
        // grouping with a cursor - so for now we just don't allow the combination at all
        throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Can not use Grouping with " + CursorMarkParams.CURSOR_MARK_PARAM);
    }
    SolrIndexSearcher searcher = rb.req.getSearcher();
    GroupingSpecification groupingSpec = new GroupingSpecification();
    rb.setGroupingSpec(groupingSpec);
    final SortSpec sortSpec = rb.getSortSpec();
    //TODO: move weighting of sort
    final SortSpec groupSortSpec = searcher.weightSortSpec(sortSpec, Sort.RELEVANCE);
    String withinGroupSortStr = params.get(GroupParams.GROUP_SORT);
    //TODO: move weighting of sort
    final SortSpec withinGroupSortSpec;
    if (withinGroupSortStr != null) {
        SortSpec parsedWithinGroupSortSpec = SortSpecParsing.parseSortSpec(withinGroupSortStr, req);
        withinGroupSortSpec = searcher.weightSortSpec(parsedWithinGroupSortSpec, Sort.RELEVANCE);
    } else {
        withinGroupSortSpec = new SortSpec(groupSortSpec.getSort(), groupSortSpec.getSchemaFields(), groupSortSpec.getCount(), groupSortSpec.getOffset());
    }
    withinGroupSortSpec.setOffset(params.getInt(GroupParams.GROUP_OFFSET, 0));
    withinGroupSortSpec.setCount(params.getInt(GroupParams.GROUP_LIMIT, 1));
    groupingSpec.setWithinGroupSortSpec(withinGroupSortSpec);
    groupingSpec.setGroupSortSpec(groupSortSpec);
    String formatStr = params.get(GroupParams.GROUP_FORMAT, Grouping.Format.grouped.name());
    Grouping.Format responseFormat;
    try {
        responseFormat = Grouping.Format.valueOf(formatStr);
    } catch (IllegalArgumentException e) {
        throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, String.format(Locale.ROOT, "Illegal %s parameter", GroupParams.GROUP_FORMAT));
    }
    groupingSpec.setResponseFormat(responseFormat);
    groupingSpec.setFields(params.getParams(GroupParams.GROUP_FIELD));
    groupingSpec.setQueries(params.getParams(GroupParams.GROUP_QUERY));
    groupingSpec.setFunctions(params.getParams(GroupParams.GROUP_FUNC));
    groupingSpec.setIncludeGroupCount(params.getBool(GroupParams.GROUP_TOTAL_COUNT, false));
    groupingSpec.setMain(params.getBool(GroupParams.GROUP_MAIN, false));
    groupingSpec.setNeedScore((rb.getFieldFlags() & SolrIndexSearcher.GET_SCORES) != 0);
    groupingSpec.setTruncateGroups(params.getBool(GroupParams.GROUP_TRUNCATE, false));
}
Also used : SolrQueryRequest(org.apache.solr.request.SolrQueryRequest) SolrParams(org.apache.solr.common.params.SolrParams) ModifiableSolrParams(org.apache.solr.common.params.ModifiableSolrParams) Grouping(org.apache.solr.search.Grouping) SolrIndexSearcher(org.apache.solr.search.SolrIndexSearcher) GroupingSpecification(org.apache.solr.search.grouping.GroupingSpecification) SolrException(org.apache.solr.common.SolrException) SortSpec(org.apache.solr.search.SortSpec)

Example 5 with SolrIndexSearcher

use of org.apache.solr.search.SolrIndexSearcher in project lucene-solr by apache.

the class QueryElevationComponent method inform.

@Override
public void inform(SolrCore core) {
    IndexSchema schema = core.getLatestSchema();
    String a = initArgs.get(FIELD_TYPE);
    if (a != null) {
        FieldType ft = schema.getFieldTypes().get(a);
        if (ft == null) {
            throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Unknown FieldType: '" + a + "' used in QueryElevationComponent");
        }
        analyzer = ft.getQueryAnalyzer();
    }
    SchemaField sf = schema.getUniqueKeyField();
    if (sf == null) {
        throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "QueryElevationComponent requires the schema to have a uniqueKeyField.");
    }
    idSchemaFT = sf.getType();
    idField = sf.getName();
    //register the EditorialMarkerFactory
    String excludeName = initArgs.get(QueryElevationParams.EXCLUDE_MARKER_FIELD_NAME, "excluded");
    if (excludeName == null || excludeName.equals("") == true) {
        excludeName = "excluded";
    }
    ExcludedMarkerFactory excludedMarkerFactory = new ExcludedMarkerFactory();
    core.addTransformerFactory(excludeName, excludedMarkerFactory);
    ElevatedMarkerFactory elevatedMarkerFactory = new ElevatedMarkerFactory();
    String markerName = initArgs.get(QueryElevationParams.EDITORIAL_MARKER_FIELD_NAME, "elevated");
    if (markerName == null || markerName.equals("") == true) {
        markerName = "elevated";
    }
    core.addTransformerFactory(markerName, elevatedMarkerFactory);
    forceElevation = initArgs.getBool(QueryElevationParams.FORCE_ELEVATION, forceElevation);
    try {
        synchronized (elevationCache) {
            elevationCache.clear();
            String f = initArgs.get(CONFIG_FILE);
            if (f == null) {
                throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "QueryElevationComponent must specify argument: '" + CONFIG_FILE + "' -- path to elevate.xml");
            }
            boolean exists = false;
            // check if using ZooKeeper
            ZkController zkController = core.getCoreContainer().getZkController();
            if (zkController != null) {
                // TODO : shouldn't have to keep reading the config name when it has been read before
                exists = zkController.configFileExists(zkController.getZkStateReader().readConfigName(core.getCoreDescriptor().getCloudDescriptor().getCollectionName()), f);
            } else {
                File fC = new File(core.getResourceLoader().getConfigDir(), f);
                File fD = new File(core.getDataDir(), f);
                if (fC.exists() == fD.exists()) {
                    throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "QueryElevationComponent missing config file: '" + f + "\n" + "either: " + fC.getAbsolutePath() + " or " + fD.getAbsolutePath() + " must exist, but not both.");
                }
                if (fC.exists()) {
                    exists = true;
                    log.info("Loading QueryElevation from: " + fC.getAbsolutePath());
                    Config cfg = new Config(core.getResourceLoader(), f);
                    elevationCache.put(null, loadElevationMap(cfg));
                }
            }
            //in other words, we think this is in the data dir, not the conf dir
            if (!exists) {
                // preload the first data
                RefCounted<SolrIndexSearcher> searchHolder = null;
                try {
                    searchHolder = core.getNewestSearcher(false);
                    IndexReader reader = searchHolder.get().getIndexReader();
                    getElevationMap(reader, core);
                } finally {
                    if (searchHolder != null)
                        searchHolder.decref();
                }
            }
        }
    } catch (Exception ex) {
        throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Error initializing QueryElevationComponent.", ex);
    }
}
Also used : ExcludedMarkerFactory(org.apache.solr.response.transform.ExcludedMarkerFactory) Config(org.apache.solr.core.Config) ElevatedMarkerFactory(org.apache.solr.response.transform.ElevatedMarkerFactory) SolrIndexSearcher(org.apache.solr.search.SolrIndexSearcher) XPathExpressionException(javax.xml.xpath.XPathExpressionException) SolrException(org.apache.solr.common.SolrException) IOException(java.io.IOException) FieldType(org.apache.solr.schema.FieldType) SchemaField(org.apache.solr.schema.SchemaField) ZkController(org.apache.solr.cloud.ZkController) IndexReader(org.apache.lucene.index.IndexReader) IndexSchema(org.apache.solr.schema.IndexSchema) VersionedFile(org.apache.solr.util.VersionedFile) File(java.io.File) SolrException(org.apache.solr.common.SolrException)

Aggregations

SolrIndexSearcher (org.apache.solr.search.SolrIndexSearcher)125 SolrCore (org.apache.solr.core.SolrCore)33 NamedList (org.apache.solr.common.util.NamedList)32 SolrException (org.apache.solr.common.SolrException)31 IOException (java.io.IOException)29 ArrayList (java.util.ArrayList)24 SolrParams (org.apache.solr.common.params.SolrParams)22 SchemaField (org.apache.solr.schema.SchemaField)22 Test (org.junit.Test)22 Document (org.apache.lucene.document.Document)21 SolrInputDocument (org.apache.solr.common.SolrInputDocument)17 Term (org.apache.lucene.index.Term)16 IndexReader (org.apache.lucene.index.IndexReader)14 SolrQueryRequest (org.apache.solr.request.SolrQueryRequest)14 IndexSchema (org.apache.solr.schema.IndexSchema)14 DocList (org.apache.solr.search.DocList)14 LeafReaderContext (org.apache.lucene.index.LeafReaderContext)13 SolrDocument (org.apache.solr.common.SolrDocument)13 FieldType (org.apache.solr.schema.FieldType)13 Query (org.apache.lucene.search.Query)12