Example usage for org.apache.solr.client.solrj SolrQuery add

List of usage examples for org.apache.solr.client.solrj SolrQuery add

Introduction

In this page you can find the example usage for org.apache.solr.client.solrj SolrQuery add.

Prototype

public ModifiableSolrParams add(String name, String... val) 

Source Link

Document

Add the given values to any existing name

Usage

From source file:at.pagu.soldockr.core.QueryParser.java

License:Apache License

private void appendGroupByFields(SolrQuery solrQuery, List<Field> fields) {
    if (CollectionUtils.isEmpty(fields)) {
        return;//from ww w  .  j ava2s  .  c o m
    }

    if (fields.size() > 1) {
        // there is a bug in solj which prevents multiple grouping
        // although available via HTTP call
        throw new ApiUsageException(
                "Cannot group on more than one field with current SolrJ API. Group on single field insead");
    }

    solrQuery.set(GroupParams.GROUP, true);
    solrQuery.setParam(GroupParams.GROUP_MAIN, true);

    for (Field field : fields) {
        solrQuery.add(GroupParams.GROUP_FIELD, field.getName());
    }
}

From source file:au.org.ala.biocache.dao.SearchDAOImpl.java

License:Open Source License

/**
 * Writes the values for the first supplied facet to output stream
 *
 * @param includeCount true when the count should be included in the download
 * @param lookupName   true when a name lsid should be looked up in the bie
 *///from  w  w w.j a va2s .  c om
public void writeFacetToStream(SpatialSearchRequestParams searchParams, boolean includeCount,
        boolean lookupName, boolean includeSynonyms, boolean includeLists, OutputStream out,
        DownloadDetailsDTO dd) throws Exception {
    //set to unlimited facets
    searchParams.setFlimit(-1);
    queryFormatUtils.formatSearchQuery(searchParams);
    String queryString = searchParams.getFormattedQuery();
    SolrQuery solrQuery = initSolrQuery(searchParams, false, null);
    solrQuery.setQuery(queryString);

    //don't want any results returned
    solrQuery.setRows(0);
    searchParams.setPageSize(0);
    solrQuery.setFacetLimit(FACET_PAGE_SIZE);
    int offset = 0;
    boolean shouldLookup = lookupName
            && (searchParams.getFacets()[0].contains("_guid") || searchParams.getFacets()[0].contains("_lsid"));

    if (dd != null) {
        dd.resetCounts();
    }

    QueryResponse qr = runSolrQuery(solrQuery, searchParams);
    if (logger.isDebugEnabled()) {
        logger.debug("Retrieved facet results from server...");
    }
    if (qr.getResults().getNumFound() > 0) {
        FacetField ff = qr.getFacetField(searchParams.getFacets()[0]);

        //write the header line
        if (ff != null) {
            String[] header = new String[] { ff.getName() };
            // out.write(ff.getName().getBytes());
            if (shouldLookup) {
                header = speciesLookupService.getHeaderDetails(ff.getName(), includeCount, includeSynonyms);
            } else if (includeCount) {
                //out.write(",Count".getBytes());
                header = (String[]) ArrayUtils.add(header, "count");
            }
            if (includeLists) {
                header = (String[]) ArrayUtils.addAll(header, listsService.getTypes().toArray(new String[] {}));
            }

            CSVRecordWriter writer = new CSVRecordWriter(new CloseShieldOutputStream(out), header);
            try {
                boolean addedNullFacet = false;

                //out.write("\n".getBytes());
                //PAGE through the facets until we reach the end.
                //do not continue when null facet is already added and the next facet is only null
                while (ff.getValueCount() > 1 || !addedNullFacet
                        || (ff.getValueCount() == 1 && ff.getValues().get(0).getName() != null)) {
                    //process the "species_guid_ facet by looking up the list of guids
                    if (shouldLookup) {
                        List<String> guids = new ArrayList<String>();
                        List<Long> counts = new ArrayList<Long>();
                        List<String[]> speciesLists = new ArrayList<String[]>();
                        if (logger.isDebugEnabled()) {
                            logger.debug("Downloading " + ff.getValueCount() + " species guids");
                        }
                        for (FacetField.Count value : ff.getValues()) {
                            //only add null facet once
                            if (value.getName() == null)
                                addedNullFacet = true;
                            if (value.getCount() == 0 || (value.getName() == null && addedNullFacet))
                                continue;

                            guids.add(value.getName());
                            if (includeCount) {
                                counts.add(value.getCount());
                            }

                            //Only want to send a sub set of the list so that the URI is not too long for BIE
                            if (guids.size() == 30) {
                                //now get the list of species from the web service TODO may need to move this code
                                //handle null values being returned from the service...
                                writeTaxonDetailsToStream(guids, counts, includeCount, includeSynonyms,
                                        includeLists, writer);
                                guids.clear();
                                counts.clear();
                            }
                        }
                        //now write any guids that remain at the end of the looping
                        writeTaxonDetailsToStream(guids, counts, includeCount, includeSynonyms, includeLists,
                                writer);
                    } else {
                        //default processing of facets
                        for (FacetField.Count value : ff.getValues()) {
                            //only add null facet once
                            if (value.getName() == null)
                                addedNullFacet = true;
                            if (value.getCount() == 0 || (value.getName() == null && addedNullFacet))
                                continue;

                            String name = value.getName() != null ? value.getName() : "";
                            String[] row = includeCount ? new String[] { name, Long.toString(value.getCount()) }
                                    : new String[] { name };
                            writer.write(row);
                        }
                    }
                    offset += FACET_PAGE_SIZE;
                    if (dd != null) {
                        dd.updateCounts(FACET_PAGE_SIZE);
                    }

                    //get the next values
                    solrQuery.remove("facet.offset");
                    solrQuery.add("facet.offset", Integer.toString(offset));
                    qr = runSolrQuery(solrQuery, searchParams);
                    ff = qr.getFacetField(searchParams.getFacets()[0]);
                }
            } finally {
                writer.finalise();
            }
        }
    }
}

From source file:au.org.ala.biocache.dao.SearchDAOImpl.java

License:Open Source License

/**
 * Writes the index fields to the supplied output stream in CSV format.
 * <p>//from  ww  w . j a  va2s .co m
 * DM: refactored to split the query by month to improve performance.
 * Further enhancements possible:
 * 1) Multi threaded
 * 2) More filtering, by year or decade..
 *
 * @param downloadParams
 * @param out
 * @param includeSensitive
 * @param dd               The details of the download
 * @param checkLimit
 * @param nextExecutor     The ExecutorService to use to process results on different threads
 * @throws Exception
 */
@Override
public ConcurrentMap<String, AtomicInteger> writeResultsFromIndexToStream(
        final DownloadRequestParams downloadParams, final OutputStream out, final boolean includeSensitive,
        final DownloadDetailsDTO dd, boolean checkLimit, final ExecutorService nextExecutor) throws Exception {
    expandRequestedFields(downloadParams, true);

    if (dd != null) {
        dd.resetCounts();
    }

    long start = System.currentTimeMillis();
    final ConcurrentMap<String, AtomicInteger> uidStats = new ConcurrentHashMap<>();
    getServer();

    try {
        SolrQuery solrQuery = new SolrQuery();
        queryFormatUtils.formatSearchQuery(downloadParams);

        String dFields = downloadParams.getFields();

        if (includeSensitive) {
            //include raw latitude and longitudes
            if (dFields.contains("decimalLatitude.p")) {
                dFields = dFields.replaceFirst("decimalLatitude.p",
                        "sensitive_latitude,sensitive_longitude,decimalLatitude.p");
            } else if (dFields.contains("decimalLatitude")) {
                dFields = dFields.replaceFirst("decimalLatitude",
                        "sensitive_latitude,sensitive_longitude,decimalLatitude");
            }
            if (dFields.contains(",locality,")) {
                dFields = dFields.replaceFirst(",locality,", ",locality,sensitive_locality,");
            }
            if (dFields.contains(",locality.p,")) {
                dFields = dFields.replaceFirst(",locality.p,", ",locality.p,sensitive_locality,");
            }
        }

        StringBuilder sb = new StringBuilder(dFields);
        if (!downloadParams.getExtra().isEmpty()) {
            sb.append(",").append(downloadParams.getExtra());
        }

        String[] requestedFields = sb.toString().split(",");
        List<String>[] indexedFields;
        if (downloadFields == null) {
            //default to include everything
            java.util.List<String> mappedNames = new java.util.LinkedList<String>();
            for (int i = 0; i < requestedFields.length; i++)
                mappedNames.add(requestedFields[i]);

            indexedFields = new List[] { mappedNames, new java.util.LinkedList<String>(), mappedNames,
                    mappedNames, new ArrayList(), new ArrayList() };
        } else {
            indexedFields = downloadFields.getIndexFields(requestedFields, downloadParams.getDwcHeaders(),
                    downloadParams.getLayersServiceUrl());
        }
        //apply custom header
        String[] customHeader = dd.getRequestParams().getCustomHeader().split(",");
        for (int i = 0; i + 1 < customHeader.length; i += 2) {
            for (int j = 0; j < indexedFields[0].size(); j++) {
                if (customHeader[i].equals(indexedFields[0].get(j))) {
                    indexedFields[2].set(j, customHeader[i + 1]);
                }
            }
            for (int j = 0; j < indexedFields[4].size(); j++) {
                if (customHeader[i].equals(indexedFields[5].get(j))) {
                    indexedFields[4].set(j, customHeader[i + 1]);
                }
            }
        }
        if (logger.isDebugEnabled()) {
            logger.debug("Fields included in download: " + indexedFields[0]);
            logger.debug("Fields excluded from download: " + indexedFields[1]);
            logger.debug("The headers in downloads: " + indexedFields[2]);
            logger.debug("Analysis headers: " + indexedFields[4]);
            logger.debug("Analysis fields: " + indexedFields[5]);
        }

        //set the fields to the ones that are available in the index
        String[] fields = indexedFields[0].toArray(new String[] {});
        solrQuery.setFields(fields);
        StringBuilder qasb = new StringBuilder();
        if (!"none".equals(downloadParams.getQa())) {
            solrQuery.addField("assertions");
            if (!"all".equals(downloadParams.getQa()) && !"includeall".equals(downloadParams.getQa())) {
                //add all the qa fields
                qasb.append(downloadParams.getQa());
            }
        }
        solrQuery.addField("institution_uid").addField("collection_uid").addField("data_resource_uid")
                .addField("data_provider_uid");

        solrQuery.setQuery(downloadParams.getFormattedQuery());
        solrQuery.setFacetMinCount(1);
        solrQuery.setFacetLimit(-1);

        //get the assertion facets to add them to the download fields
        boolean getAssertionsFromFacets = "all".equals(downloadParams.getQa())
                || "includeall".equals(downloadParams.getQa());
        SolrQuery monthAssertionsQuery = getAssertionsFromFacets
                ? solrQuery.getCopy().addFacetField("month", "assertions")
                : solrQuery.getCopy().addFacetField("month");
        if (getAssertionsFromFacets) {
            //set the order for the facet to be based on the index - this will force the assertions to be returned in the same order each time
            //based on alphabetical sort.  The number of QA's may change between searches so we can't guarantee that the order won't change
            monthAssertionsQuery.add("f.assertions.facet.sort", "index");
        }
        QueryResponse facetQuery = runSolrQuery(monthAssertionsQuery, downloadParams.getFormattedFq(), 0, 0,
                "score", "asc");

        //set the totalrecords for the download details
        dd.setTotalRecords(facetQuery.getResults().getNumFound());

        //use a separately configured and smaller limit when output will be unzipped
        final long maxDownloadSize;
        if (MAX_DOWNLOAD_SIZE > unzippedLimit && out instanceof OptionalZipOutputStream
                && ((OptionalZipOutputStream) out).getType() == OptionalZipOutputStream.Type.unzipped) {
            maxDownloadSize = unzippedLimit;
        } else {
            maxDownloadSize = MAX_DOWNLOAD_SIZE;
        }

        if (checkLimit && dd.getTotalRecords() < maxDownloadSize) {
            checkLimit = false;
        }

        //get the month facets to add them to the download fields get the assertion facets.
        List<Count> splitByFacet = null;

        for (FacetField facet : facetQuery.getFacetFields()) {
            if (facet.getName().equals("assertions") && facet.getValueCount() > 0) {
                qasb.append(getQAFromFacet(facet));
            }
            if (facet.getName().equals("month") && facet.getValueCount() > 0) {
                splitByFacet = facet.getValues();
            }
        }

        if ("includeall".equals(downloadParams.getQa())) {
            qasb = getAllQAFields();
        }

        String qas = qasb.toString();

        //include sensitive fields in the header when the output will be partially sensitive
        final String[] sensitiveFields;
        final String[] notSensitiveFields;
        if (dd.getSensitiveFq() != null) {
            List<String>[] sensitiveHdr = downloadFields.getIndexFields(sensitiveSOLRHdr,
                    downloadParams.getDwcHeaders(), downloadParams.getLayersServiceUrl());

            //header for the output file
            indexedFields[2].addAll(sensitiveHdr[2]);

            //lookup for fields from sensitive queries
            sensitiveFields = org.apache.commons.lang3.ArrayUtils.addAll(
                    indexedFields[0].toArray(new String[] {}), sensitiveHdr[0].toArray(new String[] {}));

            //use general fields when sensitive data is not permitted
            notSensitiveFields = org.apache.commons.lang3.ArrayUtils
                    .addAll(indexedFields[0].toArray(new String[] {}), notSensitiveSOLRHdr);
        } else {
            sensitiveFields = new String[0];
            notSensitiveFields = fields;
        }

        //add analysis headers
        indexedFields[2].addAll(indexedFields[4]);
        final String[] analysisFields = indexedFields[5].toArray(new String[0]);

        final String[] qaFields = qas.equals("") ? new String[] {} : qas.split(",");
        String[] qaTitles = downloadFields.getHeader(qaFields, false, false);

        String[] header = org.apache.commons.lang3.ArrayUtils.addAll(indexedFields[2].toArray(new String[] {}),
                qaTitles);

        //retain output header fields and field names for inclusion of header info in the download
        StringBuilder infoFields = new StringBuilder("infoFields");
        for (String h : indexedFields[3])
            infoFields.append(",").append(h);
        for (String h : qaFields)
            infoFields.append(",").append(h);

        StringBuilder infoHeader = new StringBuilder("infoHeaders");
        for (String h : header)
            infoHeader.append(",").append(h);

        String info = infoFields.toString();
        while (info.contains(",,"))
            info = info.replace(",,", ",");
        uidStats.put(info, new AtomicInteger(-1));
        String hdr = infoHeader.toString();
        while (hdr.contains(",,"))
            hdr = hdr.replace(",,", ",");
        uidStats.put(hdr, new AtomicInteger(-2));

        //construct correct RecordWriter based on the supplied fileType
        final RecordWriterError rw = downloadParams.getFileType().equals("csv")
                ? new CSVRecordWriter(out, header, downloadParams.getSep(), downloadParams.getEsc())
                : (downloadParams.getFileType().equals("tsv") ? new TSVRecordWriter(out, header)
                        : new ShapeFileRecordWriter(tmpShapefileDir, downloadParams.getFile(), out,
                                (String[]) ArrayUtils.addAll(fields, qaFields)));

        // Requirement to be able to propagate interruptions to all other threads for this execution
        // Doing this via this variable
        final AtomicBoolean interruptFound = dd != null ? dd.getInterrupt() : new AtomicBoolean(false);

        // Create a fixed length blocking queue for buffering results before they are written
        // This also creates a push-back effect to throttle the results generating threads
        // when it fills and offers to it are delayed until the writer consumes elements from the queue
        final BlockingQueue<String[]> queue = new ArrayBlockingQueue<>(resultsQueueLength);
        // Create a sentinel that we can check for reference equality to signal the end of the queue
        final String[] sentinel = new String[0];
        // An implementation of RecordWriter that adds to an in-memory queue
        final RecordWriter concurrentWrapper = new RecordWriter() {
            private AtomicBoolean finalised = new AtomicBoolean(false);
            private AtomicBoolean finalisedComplete = new AtomicBoolean(false);

            @Override
            public void write(String[] nextLine) {
                try {
                    if (Thread.currentThread().isInterrupted() || interruptFound.get() || finalised.get()) {
                        finalise();
                        return;
                    }
                    while (!queue.offer(nextLine, writerTimeoutWaitMillis, TimeUnit.MILLISECONDS)) {
                        if (Thread.currentThread().isInterrupted() || interruptFound.get() || finalised.get()) {
                            finalise();
                            break;
                        }
                    }
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    interruptFound.set(true);
                    if (logger.isDebugEnabled()) {
                        logger.debug(
                                "Queue failed to accept the next record due to a thread interrupt, calling finalise the cleanup: ",
                                e);
                    }
                    // If we were interrupted then we should call finalise to cleanup
                    finalise();
                }
            }

            @Override
            public void finalise() {
                if (finalised.compareAndSet(false, true)) {
                    try {
                        // Offer the sentinel at least once, even when the thread is interrupted
                        while (!queue.offer(sentinel, writerTimeoutWaitMillis, TimeUnit.MILLISECONDS)) {
                            // If the thread is interrupted then the queue may not have any active consumers,
                            // so don't loop forever waiting for capacity in this case
                            // The hard shutdown phase will use queue.clear to ensure that the
                            // sentinel gets onto the queue at least once
                            if (Thread.currentThread().isInterrupted() || interruptFound.get()) {
                                break;
                            }
                        }
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                        interruptFound.set(true);
                        if (logger.isDebugEnabled()) {
                            logger.debug(
                                    "Queue failed to accept the sentinel in finalise due to a thread interrupt: ",
                                    e);
                        }
                    } finally {
                        finalisedComplete.set(true);
                    }
                }
            }

            @Override
            public boolean finalised() {
                return finalisedComplete.get();
            }

        };

        // A single thread that consumes elements put onto the queue until it sees the sentinel, finalising after the sentinel or an interrupt
        Runnable writerRunnable = new Runnable() {
            @Override
            public void run() {
                try {
                    long counter = 0;
                    while (true) {
                        counter = counter + 1;

                        if (Thread.currentThread().isInterrupted() || interruptFound.get()) {
                            break;
                        }

                        String[] take = queue.take();
                        // Sentinel object equality check to see if we are done
                        if (take == sentinel || Thread.currentThread().isInterrupted()
                                || interruptFound.get()) {
                            break;
                        }
                        // Otherwise write to the wrapped record writer
                        rw.write(take);

                        //test for errors. This can contain a flush so only test occasionally
                        if (counter % resultsQueueLength == 0 && rw.hasError()) {
                            throw RecordWriterException.newRecordWriterException(dd, downloadParams, true, rw);
                        }

                    }
                } catch (RecordWriterException e) {
                    //no trace information is available to print for these errors
                    logger.error(e.getMessage());
                    interruptFound.set(true);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    interruptFound.set(true);
                } catch (Exception e) {
                    // Reuse interruptFound variable to signal that the writer had issues
                    interruptFound.set(true);
                    logger.error("Download writer failed.", e);
                } finally {
                    rw.finalise();
                }
            }
        };
        Thread writerThread = new Thread(writerRunnable);
        writerThread.start();

        try {
            if (rw instanceof ShapeFileRecordWriter) {
                dd.setHeaderMap(((ShapeFileRecordWriter) rw).getHeaderMappings());
            }

            //order the query by _docid_ for faster paging
            solrQuery.addSortField("_docid_", ORDER.asc);

            //for each month create a separate query that pages through 500 records per page
            List<SolrQuery> queries = new ArrayList<SolrQuery>();
            if (splitByFacet != null) {
                for (Count facet : splitByFacet) {
                    if (facet.getCount() > 0) {
                        SolrQuery splitByFacetQuery;
                        //do not add remainderQuery here
                        if (facet.getName() != null) {
                            splitByFacetQuery = solrQuery.getCopy()
                                    .addFilterQuery(facet.getFacetField().getName() + ":" + facet.getName());
                            splitByFacetQuery.setFacet(false);
                            queries.add(splitByFacetQuery);
                        }

                    }
                }
                if (splitByFacet.size() > 0) {
                    SolrQuery remainderQuery = solrQuery.getCopy()
                            .addFilterQuery("-" + splitByFacet.get(0).getFacetField().getName() + ":[* TO *]");
                    queries.add(0, remainderQuery);
                }
            } else {
                queries.add(0, solrQuery);
            }

            //split into sensitive and non-sensitive queries when
            // - not including all sensitive values
            // - there is a sensitive fq
            final List<SolrQuery> sensitiveQ = new ArrayList<SolrQuery>();
            if (!includeSensitive && dd.getSensitiveFq() != null) {
                sensitiveQ.addAll(
                        splitQueries(queries, dd.getSensitiveFq(), sensitiveSOLRHdr, notSensitiveSOLRHdr));
            }

            //Set<Future<Integer>> futures = new HashSet<Future<Integer>>();
            final AtomicInteger resultsCount = new AtomicInteger(0);
            final boolean threadCheckLimit = checkLimit;

            List<Callable<Integer>> solrCallables = new ArrayList<>(queries.size());
            // execute each query, writing the results to stream
            for (final SolrQuery splitByFacetQuery : queries) {
                // define a thread
                Callable<Integer> solrCallable = new Callable<Integer>() {
                    @Override
                    public Integer call() throws Exception {
                        int startIndex = 0;
                        // Randomise the wakeup time so they don't all wakeup on a periodic cycle
                        long localThrottle = throttle + Math.round(Math.random() * throttle);

                        String[] fq = downloadParams.getFormattedFq();
                        if (splitByFacetQuery.getFilterQueries() != null
                                && splitByFacetQuery.getFilterQueries().length > 0) {
                            if (fq == null) {
                                fq = new String[0];
                            }
                            fq = org.apache.commons.lang3.ArrayUtils.addAll(fq,
                                    splitByFacetQuery.getFilterQueries());
                        }

                        QueryResponse qr = runSolrQuery(splitByFacetQuery, fq, downloadBatchSize, startIndex,
                                "_docid_", "asc");
                        AtomicInteger recordsForThread = new AtomicInteger(0);
                        if (logger.isDebugEnabled()) {
                            logger.debug(
                                    splitByFacetQuery.getQuery() + " - results: " + qr.getResults().size());
                        }

                        while (qr != null && !qr.getResults().isEmpty() && !interruptFound.get()) {
                            if (logger.isDebugEnabled()) {
                                logger.debug(
                                        "Start index: " + startIndex + ", " + splitByFacetQuery.getQuery());
                            }
                            int count = 0;
                            if (sensitiveQ.contains(splitByFacetQuery)) {
                                count = processQueryResults(uidStats, sensitiveFields, qaFields,
                                        concurrentWrapper, qr, dd, threadCheckLimit, resultsCount,
                                        maxDownloadSize, analysisFields);
                            } else {
                                // write non-sensitive values into sensitive fields when not authorised for their sensitive values
                                count = processQueryResults(uidStats, notSensitiveFields, qaFields,
                                        concurrentWrapper, qr, dd, threadCheckLimit, resultsCount,
                                        maxDownloadSize, analysisFields);
                            }
                            recordsForThread.addAndGet(count);
                            startIndex += downloadBatchSize;
                            // we have already set the Filter query the first time the query was constructed
                            // rerun with the same params but different startIndex
                            if (!threadCheckLimit || resultsCount.get() < maxDownloadSize) {
                                if (!threadCheckLimit) {
                                    // throttle the download by sleeping
                                    Thread.sleep(localThrottle);
                                }
                                qr = runSolrQuery(splitByFacetQuery, null, downloadBatchSize, startIndex,
                                        "_docid_", "asc");
                            } else {
                                qr = null;
                            }
                        }
                        return recordsForThread.get();
                    }
                };
                solrCallables.add(solrCallable);
            }

            List<Future<Integer>> futures = new ArrayList<>(solrCallables.size());
            for (Callable<Integer> nextCallable : solrCallables) {
                futures.add(nextExecutor.submit(nextCallable));
            }

            // Busy wait because we need to be able to respond to an interrupt on any callable
            // and propagate it to all of the others for this particular query
            // Because the executor service is shared to prevent too many concurrent threads being run,
            // this requires a busy wait loop on the main thread to monitor state
            boolean waitAgain = false;
            do {
                waitAgain = false;
                for (Future<Integer> future : futures) {
                    if (!future.isDone()) {
                        // Wait again even if an interrupt flag is set, as it may have been set partway through the iteration
                        // The calls to future.cancel will occur next time if the interrupt is setup partway through an iteration
                        waitAgain = true;
                        // If one thread finds an interrupt it is propagated to others using the interruptFound AtomicBoolean
                        if (interruptFound.get()) {
                            future.cancel(true);
                        }
                    }
                }
                // Don't trigger the timeout interrupt if we don't have to wait again as we are already done at this point
                if (waitAgain && (System.currentTimeMillis() - start) > downloadMaxTime) {
                    interruptFound.set(true);
                    break;
                }

                if (waitAgain) {
                    Thread.sleep(downloadCheckBusyWaitSleep);
                }
            } while (waitAgain);

            AtomicInteger totalDownload = new AtomicInteger(0);
            for (Future<Integer> future : futures) {
                if (future.isDone()) {
                    totalDownload.addAndGet(future.get());
                } else {
                    // All incomplete futures that survived the loop above are cancelled here
                    future.cancel(true);
                }
            }

            long finish = System.currentTimeMillis();
            long timeTakenInSecs = (finish - start) / 1000;
            if (timeTakenInSecs <= 0)
                timeTakenInSecs = 1;
            if (logger.isInfoEnabled()) {
                logger.info("Download of " + resultsCount + " records in " + timeTakenInSecs
                        + " seconds. Record/sec: " + resultsCount.intValue() / timeTakenInSecs);
            }

        } finally {
            try {
                // Once we get here, we need to finalise starting at the concurrent wrapper,
                // as there are no more non-sentinel records to be added to the queue
                // This eventually triggers finalisation of the underlying writer when the queue empties
                // This is a soft shutdown, and hence we wait below for this stage to complete in normal circumstances
                // Note, this blocks for writerTimeoutWaitMillis trying to legitimately add the sentinel to the end of the queue
                // We force the sentinel to be added in the hard shutdown phase below
                concurrentWrapper.finalise();
            } finally {
                try {
                    // Track the current time right now so we can abort after downloadMaxCompletionTime milliseconds in this phase
                    final long completionStartTime = System.currentTimeMillis();
                    // Busy wait check for finalised to be called in the RecordWriter or something is interrupted
                    // By this stage, there are at maximum download.internal.queue.size items remaining (default 1000)
                    while (writerThread.isAlive() && !writerThread.isInterrupted() && !interruptFound.get()
                            && !Thread.currentThread().isInterrupted() && !rw.finalised()
                            && !((System.currentTimeMillis()
                                    - completionStartTime) > downloadMaxCompletionTime)) {
                        Thread.sleep(downloadCheckBusyWaitSleep);
                    }
                } finally {
                    try {
                        // Attempt all actions that could trigger the writer thread to finalise, as by this stage we are in hard shutdown mode

                        // Signal that we are in hard shutdown mode
                        interruptFound.set(true);

                        // Add the sentinel or clear the queue and try again until it gets onto the queue
                        // We are in hard shutdown mode, so only priority is that the queue either
                        // gets the sentinel or the thread is interrupted to clean up resources
                        while (!queue.offer(sentinel)) {
                            queue.clear();
                        }

                        // Interrupt the single writer thread
                        writerThread.interrupt();

                        // Explicitly call finalise on the RecordWriter as a backup
                        // In normal circumstances it is called via the sentinel or the interrupt
                        // This will not block if finalise has been called previously in the current three implementations
                        rw.finalise();
                    } finally {
                        if (rw != null && rw.hasError()) {
                            throw RecordWriterException.newRecordWriterException(dd, downloadParams, true, rw);
                        } else {
                            // Flush whatever output was still pending for more deterministic debugging
                            out.flush();
                        }
                    }
                }
            }
        }
    } catch (SolrServerException ex) {
        logger.error("Problem communicating with SOLR server while processing download. " + ex.getMessage(),
                ex);
    }
    return uidStats;
}

From source file:au.org.ala.biocache.dao.SearchDAOImpl.java

License:Open Source License

/**
 * Note - this method extracts from CASSANDRA rather than the Index.
 *//*from ww w .ja va 2s  .  c o  m*/
public ConcurrentMap<String, AtomicInteger> writeResultsToStream(DownloadRequestParams downloadParams,
        OutputStream out, int i, boolean includeSensitive, DownloadDetailsDTO dd, boolean limit)
        throws Exception {
    expandRequestedFields(downloadParams, false);

    int resultsCount = 0;
    ConcurrentMap<String, AtomicInteger> uidStats = new ConcurrentHashMap<>();
    //stores the remaining limit for data resources that have a download limit
    Map<String, Integer> downloadLimit = new HashMap<>();

    try {
        SolrQuery solrQuery = initSolrQuery(downloadParams, false, null);
        //ensure that the qa facet is being ordered alphabetically so that the order is consistent.
        boolean getAssertionsFromFacets = "all".equals(downloadParams.getQa())
                || "includeall".equals(downloadParams.getQa());
        if (getAssertionsFromFacets) {
            //set the order for the facet to be based on the index - this will force the assertions to be returned in the same order each time
            //based on alphabetical sort.  The number of QA's may change between searches so we can't guarantee that the order won't change
            solrQuery.add("f.assertions.facet.sort", "index");
        }
        queryFormatUtils.formatSearchQuery(downloadParams);
        if (logger.isInfoEnabled()) {
            logger.info("search query: " + downloadParams.getFormattedQuery());
        }
        solrQuery.setQuery(downloadParams.getFormattedQuery());
        //Only the fields specified below will be included in the results from the SOLR Query
        solrQuery.setFields("row_key", "institution_uid", "collection_uid", "data_resource_uid",
                "data_provider_uid");

        String dFields = downloadParams.getFields();

        if (includeSensitive) {
            //include raw latitude and longitudes
            dFields = dFields
                    .replaceFirst("decimalLatitude.p", "decimalLatitude,decimalLongitude,decimalLatitude.p")
                    .replaceFirst(",locality,", ",locality,sensitive_locality,");
        }

        StringBuilder sb = new StringBuilder(dFields);
        if (downloadParams.getExtra().length() > 0) {
            sb.append(",").append(downloadParams.getExtra());
        }
        StringBuilder qasb = new StringBuilder();

        solrQuery.setFacet(true);
        QueryResponse qr = runSolrQuery(solrQuery, downloadParams.getFormattedFq(), 0, 0, "_docid_", "asc");
        dd.setTotalRecords(qr.getResults().getNumFound());
        //get the assertion facets to add them to the download fields
        List<FacetField> facets = qr.getFacetFields();
        for (FacetField facet : facets) {
            if (facet.getName().equals("assertions") && facet.getValueCount() > 0) {
                qasb.append(getQAFromFacet(facet));
            } else if (facet.getName().equals("data_resource_uid") && checkDownloadLimits) {
                //populate the download limit
                initDownloadLimits(downloadLimit, facet);
            }
        }

        if ("includeall".equals(downloadParams.getQa())) {
            qasb = getAllQAFields();
        }

        //Write the header line
        String qas = qasb.toString();

        List<String>[] indexedFields = downloadFields.getIndexFields(downloadParams.getFields().split(","),
                false, downloadParams.getLayersServiceUrl());

        String[] fields = sb.toString().split(",");

        //avoid analysis field duplicates
        for (String s : indexedFields[5])
            fields = (String[]) ArrayUtils.removeElement(fields, s);

        String[] qaFields = qas.equals("") ? new String[] {} : qas.split(",");
        String[] qaTitles = downloadFields.getHeader(qaFields, false, false);
        String[] titles = downloadFields.getHeader(fields, true, downloadParams.getDwcHeaders());
        String[] analysisHeaders = indexedFields[4].toArray(new String[0]);
        String[] analysisFields = indexedFields[5].toArray(new String[0]);

        //apply custom header
        String[] customHeader = dd.getRequestParams().getCustomHeader().split(",");
        for (i = 0; i + 1 < customHeader.length; i += 2) {
            for (int j = 0; j < analysisFields.length; j++) {
                if (customHeader[i].equals(analysisFields[j])) {
                    analysisFields[j] = customHeader[i + 1];
                }
            }
            for (int j = 0; j < qaFields.length; j++) {
                if (customHeader[i].equals(qaFields[j])) {
                    qaTitles[j] = customHeader[i + 1];
                }
            }
            for (int j = 0; j < fields.length; j++) {
                if (customHeader[i].equals(fields[j])) {
                    titles[j] = customHeader[i + 1];
                }
            }
        }

        //append sensitive fields for the header only
        if (!includeSensitive && dd.getSensitiveFq() != null) {
            //sensitive headers do not have a DwC name, always set getIndexFields dwcHeader=false
            List<String>[] sensitiveHdr = downloadFields.getIndexFields(sensitiveSOLRHdr, false,
                    downloadParams.getLayersServiceUrl());

            titles = org.apache.commons.lang3.ArrayUtils.addAll(titles,
                    sensitiveHdr[2].toArray(new String[] {}));
        }
        String[] header = org.apache.commons.lang3.ArrayUtils
                .addAll(org.apache.commons.lang3.ArrayUtils.addAll(titles, qaTitles), analysisHeaders);
        //Create the Writer that will be used to format the records
        //construct correct RecordWriter based on the supplied fileType
        final RecordWriterError rw = downloadParams.getFileType().equals("csv")
                ? new CSVRecordWriter(out, header, downloadParams.getSep(), downloadParams.getEsc())
                : (downloadParams.getFileType().equals("tsv") ? new TSVRecordWriter(out, header)
                        : new ShapeFileRecordWriter(tmpShapefileDir, downloadParams.getFile(), out,
                                (String[]) ArrayUtils.addAll(fields, qaFields)));

        try {
            if (rw instanceof ShapeFileRecordWriter) {
                dd.setHeaderMap(((ShapeFileRecordWriter) rw).getHeaderMappings());
            }

            //retain output header fields and field names for inclusion of header info in the download
            StringBuilder infoFields = new StringBuilder("infoFields,");
            for (String h : fields)
                infoFields.append(",").append(h);
            for (String h : analysisFields)
                infoFields.append(",").append(h);
            for (String h : qaFields)
                infoFields.append(",").append(h);

            StringBuilder infoHeader = new StringBuilder("infoHeaders,");
            for (String h : header)
                infoHeader.append(",").append(h);

            String info = infoFields.toString();
            while (info.contains(",,"))
                info = info.replace(",,", ",");
            uidStats.put(info, new AtomicInteger(-1));
            String hdr = infoHeader.toString();
            while (hdr.contains(",,"))
                hdr = hdr.replace(",,", ",");
            uidStats.put(hdr, new AtomicInteger(-2));

            //download the records that have limits first...
            if (downloadLimit.size() > 0) {
                String[] originalFq = downloadParams.getFormattedFq();
                StringBuilder fqBuilder = new StringBuilder("-(");
                for (String dr : downloadLimit.keySet()) {
                    //add another fq to the search for data_resource_uid
                    downloadParams.setFq((String[]) ArrayUtils.add(originalFq, "data_resource_uid:" + dr));
                    resultsCount = downloadRecords(downloadParams, rw, downloadLimit, uidStats, fields,
                            qaFields, resultsCount, dr, includeSensitive, dd, limit, analysisFields);
                    if (fqBuilder.length() > 2) {
                        fqBuilder.append(" OR ");
                    }
                    fqBuilder.append("data_resource_uid:").append(dr);
                }
                fqBuilder.append(")");
                //now include the rest of the data resources
                //add extra fq for the remaining records
                downloadParams.setFq((String[]) ArrayUtils.add(originalFq, fqBuilder.toString()));
                resultsCount = downloadRecords(downloadParams, rw, downloadLimit, uidStats, fields, qaFields,
                        resultsCount, null, includeSensitive, dd, limit, analysisFields);
            } else {
                //download all at once
                downloadRecords(downloadParams, rw, downloadLimit, uidStats, fields, qaFields, resultsCount,
                        null, includeSensitive, dd, limit, analysisFields);
            }
        } finally {
            rw.finalise();
        }
    } catch (SolrServerException ex) {
        logger.error("Problem communicating with SOLR server. " + ex.getMessage(), ex);
    }

    return uidStats;
}

From source file:au.org.ala.biocache.dao.SearchDAOImpl.java

License:Open Source License

protected void initDecadeBasedFacet(SolrQuery solrQuery, String field) {
    solrQuery.add("facet.date", field);
    solrQuery.add("facet.date.start", DECADE_FACET_START_DATE); // facet date range starts from 1850
    solrQuery.add("facet.date.end", "NOW/DAY"); // facet date range ends for current date (gap period)
    solrQuery.add("facet.date.gap", "+10YEAR"); // gap interval of 10 years
    solrQuery.add("facet.date.other", DECADE_PRE_1850_LABEL); // include counts before the facet start date ("before" label)
    solrQuery.add("facet.date.include", "lower"); // counts will be included for dates on the starting date but not ending date
}

From source file:au.org.ala.biocache.dao.SearchDAOImpl.java

License:Open Source License

/**
 * Helper method to create SolrQuery object and add facet settings
 *
 * @return solrQuery the SolrQuery/*from   w w  w . j a  v a  2 s .  c o  m*/
 */
protected SolrQuery initSolrQuery(SearchRequestParams searchParams, boolean substituteDefaultFacetOrder,
        Map<String, String[]> extraSolrParams) {

    SolrQuery solrQuery = new SolrQuery();
    solrQuery.setQueryType("standard");
    boolean rangeAdded = false;
    // Facets
    solrQuery.setFacet(searchParams.getFacet());
    if (searchParams.getFacet()) {
        for (String facet : searchParams.getFacets()) {
            if (facet.equals("date") || facet.equals("decade")) {
                String fname = facet.equals("decade") ? OCCURRENCE_YEAR_INDEX_FIELD : "occurrence_" + facet;
                initDecadeBasedFacet(solrQuery, fname);
            } else if (facet.equals("uncertainty")) {
                Map<String, String> rangeMap = rangeBasedFacets.getRangeMap("uncertainty");
                for (String range : rangeMap.keySet()) {
                    solrQuery.add("facet.query", range);
                }
            } else if (facet.endsWith(RANGE_SUFFIX)) {
                //this facte need to have it ranges included.
                if (!rangeAdded) {
                    solrQuery.add("facet.range.other", "before");
                    solrQuery.add("facet.range.other", "after");
                }
                String field = facet.replaceAll(RANGE_SUFFIX, "");
                StatsIndexFieldDTO details = getRangeFieldDetails(field);
                if (details != null) {
                    solrQuery.addNumericRangeFacet(field, details.getStart(), details.getEnd(),
                            details.getGap());
                }
            } else {
                solrQuery.addFacetField(facet);

                if ("".equals(searchParams.getFsort()) && substituteDefaultFacetOrder
                        && FacetThemes.getFacetsMap().containsKey(facet)) {
                    //now check if the sort order is different to supplied
                    String thisSort = FacetThemes.getFacetsMap().get(facet).getSort();
                    if (!searchParams.getFsort().equalsIgnoreCase(thisSort))
                        solrQuery.add("f." + facet + ".facet.sort", thisSort);
                }

            }
        }

        solrQuery.setFacetMinCount(1);
        solrQuery.setFacetLimit(searchParams.getFlimit());
        //include this so that the default fsort is still obeyed.
        String fsort = "".equals(searchParams.getFsort()) ? "count" : searchParams.getFsort();
        solrQuery.setFacetSort(fsort);
        if (searchParams.getFoffset() > 0)
            solrQuery.add("facet.offset", Integer.toString(searchParams.getFoffset()));
        if (StringUtils.isNotEmpty(searchParams.getFprefix()))
            solrQuery.add("facet.prefix", searchParams.getFprefix());
    }

    solrQuery.setRows(10);
    solrQuery.setStart(0);

    if (searchParams.getFl().length() > 0) {
        solrQuery.setFields(searchParams.getFl());
    }

    //add the extra SOLR params
    if (extraSolrParams != null) {
        //automatically include the before and after params...
        if (!rangeAdded) {
            solrQuery.add("facet.range.other", "before");
            solrQuery.add("facet.range.other", "after");
        }
        for (String key : extraSolrParams.keySet()) {
            String[] values = extraSolrParams.get(key);
            solrQuery.add(key, values);
        }
    }
    return solrQuery;
}

From source file:au.org.ala.biocache.dao.SearchDAOImpl.java

License:Open Source License

/**
 * Get a distinct list of species and their counts using a facet search
 *
 * @param queryString//from   w  w w  . jav a  2s . com
 * @param pageSize
 * @param sortField
 * @param sortDirection
 * @return
 * @throws SolrServerException
 */
protected List<TaxaCountDTO> getSpeciesCounts(String queryString, List<String> filterQueries,
        List<String> facetFields, Integer pageSize, Integer startIndex, String sortField, String sortDirection)
        throws SolrServerException {

    List<TaxaCountDTO> speciesCounts = new ArrayList<TaxaCountDTO>();
    SolrQuery solrQuery = new SolrQuery();
    solrQuery.setQueryType("standard");
    solrQuery.setQuery(queryString);

    if (filterQueries != null && filterQueries.size() > 0) {
        //solrQuery.addFilterQuery("(" + StringUtils.join(filterQueries, " OR ") + ")");
        for (String fq : filterQueries) {
            solrQuery.addFilterQuery(fq);
        }
    }
    solrQuery.setRows(0);
    solrQuery.setFacet(true);
    solrQuery.setFacetSort(sortField);
    for (String facet : facetFields) {
        solrQuery.addFacetField(facet);
        if (logger.isDebugEnabled()) {
            logger.debug("adding facetField: " + facet);
        }
    }
    //set the facet starting point based on the paging information
    solrQuery.setFacetMinCount(1);
    solrQuery.setFacetLimit(pageSize); // unlimited = -1 | pageSize
    solrQuery.add("facet.offset", Integer.toString(startIndex));
    if (logger.isDebugEnabled()) {
        logger.debug("getSpeciesCount query :" + solrQuery.getQuery());
    }
    QueryResponse qr = runSolrQuery(solrQuery, null, 1, 0, "score", sortDirection);
    if (logger.isInfoEnabled()) {
        logger.info("SOLR query: " + solrQuery.getQuery() + "; total hits: " + qr.getResults().getNumFound());
    }
    List<FacetField> facets = qr.getFacetFields();
    java.util.regex.Pattern p = java.util.regex.Pattern.compile("\\|");

    if (facets != null && facets.size() > 0) {
        if (logger.isDebugEnabled()) {
            logger.debug("Facets: " + facets.size() + "; facet #1: " + facets.get(0).getName());
        }
        for (FacetField facet : facets) {
            List<FacetField.Count> facetEntries = facet.getValues();
            if ((facetEntries != null) && (facetEntries.size() > 0)) {

                for (FacetField.Count fcount : facetEntries) {
                    TaxaCountDTO tcDTO = null;
                    String name = fcount.getName() != null ? fcount.getName() : "";
                    if (fcount.getFacetField().getName().equals(NAMES_AND_LSID)) {
                        String[] values = p.split(name, 5);

                        if (values.length >= 5) {
                            if (!"||||".equals(name)) {
                                tcDTO = new TaxaCountDTO(values[0], fcount.getCount());
                                tcDTO.setGuid(StringUtils.trimToNull(values[1]));
                                tcDTO.setCommonName(values[2]);
                                tcDTO.setKingdom(values[3]);
                                tcDTO.setFamily(values[4]);
                                if (StringUtils.isNotEmpty(tcDTO.getGuid()))
                                    tcDTO.setRank(searchUtils.getTaxonSearch(tcDTO.getGuid())[1].split(":")[0]);
                            }
                        } else {
                            if (logger.isDebugEnabled()) {
                                logger.debug("The values length: " + values.length + " :" + name);
                            }
                            tcDTO = new TaxaCountDTO(name, fcount.getCount());
                        }
                        //speciesCounts.add(i, tcDTO);
                        if (tcDTO != null && tcDTO.getCount() > 0)
                            speciesCounts.add(tcDTO);
                    } else if (fcount.getFacetField().getName().equals(COMMON_NAME_AND_LSID)) {
                        String[] values = p.split(name, 6);

                        if (values.length >= 5) {
                            if (!"|||||".equals(name)) {
                                tcDTO = new TaxaCountDTO(values[1], fcount.getCount());
                                tcDTO.setGuid(StringUtils.trimToNull(values[2]));
                                tcDTO.setCommonName(values[0]);
                                //cater for the bug of extra vernacular name in the result
                                tcDTO.setKingdom(values[values.length - 2]);
                                tcDTO.setFamily(values[values.length - 1]);
                                if (StringUtils.isNotEmpty(tcDTO.getGuid()))
                                    tcDTO.setRank(searchUtils.getTaxonSearch(tcDTO.getGuid())[1].split(":")[0]);
                            }
                        } else {
                            if (logger.isDebugEnabled()) {
                                logger.debug("The values length: " + values.length + " :" + name);
                            }
                            tcDTO = new TaxaCountDTO(name, fcount.getCount());
                        }
                        //speciesCounts.add(i, tcDTO);
                        if (tcDTO != null && tcDTO.getCount() > 0) {
                            speciesCounts.add(tcDTO);
                        }
                    }
                }
            }
        }
    }

    return speciesCounts;
}

From source file:au.org.ala.biocache.dao.SearchDAOImpl.java

License:Open Source License

/**
 * Returns the count of distinct values for the facets.  Uses groups for group counts.
 * Supports foffset and flimit for paging. Supports fsort 'count' or 'index'.
 * <p/>//from   w  w  w .  j a  v  a2s.co  m
 * TODO work out whether or not we should allow facet ranges to be downloaded....
 */
public List<FacetResultDTO> getFacetCounts(SpatialSearchRequestParams searchParams) throws Exception {
    Collection<FacetResultDTO> facetResults = new ArrayList<FacetResultDTO>();

    queryFormatUtils.formatSearchQuery(searchParams);
    String queryString = searchParams.getFormattedQuery();
    searchParams.setFacet(false);
    searchParams.setPageSize(0);

    //get facet group counts
    SolrQuery query = initSolrQuery(searchParams, false, null);
    query.setQuery(queryString);
    query.setFields(null);
    query.setRows(0);
    searchParams.setPageSize(0);

    //exclude multivalue fields
    Set<IndexFieldDTO> fields = getIndexedFields();
    List<String> multivalueFields = new ArrayList<String>();
    for (String facet : searchParams.getFacets()) {
        boolean added = false;
        for (IndexFieldDTO f : fields) {
            if (f.getName().equals(facet) && !f.isMultivalue()) {
                query.add("group.field", facet);
                added = true;
            }
        }
        if (!added) {
            multivalueFields.add(facet);
        }
    }

    if (multivalueFields.size() > 0) {
        facetResults.addAll(getMultivalueFacetCounts(query, searchParams, multivalueFields));
    }

    if (multivalueFields.size() < searchParams.getFacets().length) {
        //now use the supplied facets to add groups to the query

        // facet totals are slow, so only fetch when foffset == 0 and flimit != -1
        Map<String, Integer> ngroups = new HashMap<String, Integer>();
        GroupResponse groupResponse = null;
        if (searchParams.getFlimit() != -1 && searchParams.getFoffset() == 0) {
            query.add("group", "true");
            query.add("group.ngroups", "true");
            query.add("group.limit", "0");

            QueryResponse response = runSolrQuery(query, searchParams);
            groupResponse = response.getGroupResponse();
            for (GroupCommand gc : groupResponse.getValues()) {
                ngroups.put(gc.getName(), gc.getNGroups());
            }
        }

        //include paged facets when flimit > 0 or flimit == -1
        if (searchParams.getFlimit() != 0) {
            searchParams.setFacet(true);
            SolrQuery facetQuery = initSolrQuery(searchParams, false, null);
            facetQuery.setQuery(queryString);
            facetQuery.setFields(null);
            facetQuery.setSortField(searchParams.getSort(), ORDER.valueOf(searchParams.getDir()));
            QueryResponse qr = runSolrQuery(facetQuery, searchParams);
            SearchResultDTO searchResults = processSolrResponse(searchParams, qr, facetQuery,
                    OccurrenceIndex.class);
            facetResults = searchResults.getFacetResults();
            if (facetResults != null) {
                for (FacetResultDTO fr : facetResults) {
                    if (searchParams.getFlimit() == -1) {
                        fr.setCount(fr.getFieldResult().size());
                    } else {
                        Integer count = ngroups.get(fr.getFieldName());
                        if (count != null)
                            fr.setCount(count);
                    }
                }
            }
        } else if (groupResponse != null) {
            //only return group counts
            for (GroupCommand gc : groupResponse.getValues()) {
                facetResults.add(new FacetResultDTO(gc.getName(), null, gc.getNGroups()));
            }
        }
    }

    return new ArrayList<FacetResultDTO>(facetResults);
}

From source file:au.org.ala.biocache.dao.SearchDAOImpl.java

License:Open Source License

public Map<String, Integer> getOccurrenceCountsForTaxa(List<String> taxa) throws Exception {
    SolrQuery solrQuery = new SolrQuery();
    solrQuery.setQueryType("standard");
    solrQuery.setRows(0);// w ww  . j  a  va  2 s .  c  o m
    solrQuery.setFacet(true);
    solrQuery.setFacetLimit(taxa.size());
    StringBuilder sb = new StringBuilder();
    Map<String, Integer> counts = new HashMap<String, Integer>();
    Map<String, String> lftToGuid = new HashMap<String, String>();
    for (String lsid : taxa) {
        //get the lft and rgt value for the taxon
        String[] values = searchUtils.getTaxonSearch(lsid);
        //first value is the search string
        if (sb.length() > 0)
            sb.append(" OR ");
        sb.append(values[0]);
        lftToGuid.put(values[0], lsid);
        //add the query part as a facet
        solrQuery.add("facet.query", values[0]);
    }
    solrQuery.setQuery(sb.toString());

    //solrQuery.add("facet.query", "confidence:" + os.getRange());
    QueryResponse qr = runSolrQuery(solrQuery, null, 1, 0, "score", "asc");
    Map<String, Integer> facetQueries = qr.getFacetQuery();
    for (String facet : facetQueries.keySet()) {
        //add all the counts based on the query value that was substituted
        String lsid = lftToGuid.get(facet);
        Integer count = facetQueries.get(facet);
        if (lsid != null && count != null)
            counts.put(lsid, count);
    }
    if (logger.isDebugEnabled()) {
        logger.debug(facetQueries);
    }
    return counts;
}

From source file:au.org.ala.biocache.dao.SearchDAOImpl.java

License:Open Source License

/**
 * Perform grouped facet query.// w  w w  . ja  v  a 2  s  .co  m
 * <p>
 * facets is the list of grouped facets required
 * flimit restricts the number of groups returned
 * pageSize restricts the number of docs in each group returned
 * fl is the list of fields in the returned docs
 */
public List<GroupFacetResultDTO> searchGroupedFacets(SpatialSearchRequestParams searchParams) throws Exception {
    queryFormatUtils.formatSearchQuery(searchParams);
    String queryString = searchParams.getFormattedQuery();
    searchParams.setFacet(false);

    //get facet group counts
    SolrQuery query = initSolrQuery(searchParams, false, null);
    query.setQuery(queryString);
    query.setFields(null);
    //now use the supplied facets to add groups to the query
    query.add("group", "true");
    query.add("group.ngroups", "true");
    query.add("group.limit", String.valueOf(searchParams.getPageSize()));
    query.setRows(searchParams.getFlimit());
    query.setFields(searchParams.getFl());
    for (String facet : searchParams.getFacets()) {
        query.add("group.field", facet);
    }
    QueryResponse response = runSolrQuery(query, searchParams);
    GroupResponse groupResponse = response.getGroupResponse();

    List<GroupFacetResultDTO> output = new ArrayList();
    for (GroupCommand gc : groupResponse.getValues()) {
        List<GroupFieldResultDTO> list = new ArrayList<GroupFieldResultDTO>();

        String facet = gc.getName();
        for (Group v : gc.getValues()) {
            List<OccurrenceIndex> docs = (new DocumentObjectBinder()).getBeans(OccurrenceIndex.class,
                    v.getResult());

            //build facet displayName and fq
            String value = v.getGroupValue();
            Long count = v.getResult() != null ? v.getResult().getNumFound() : 0L;
            if (value == null) {
                list.add(new GroupFieldResultDTO("", count, "-" + facet + ":*", docs));
            } else {
                list.add(new GroupFieldResultDTO(getFacetValueDisplayName(facet, value), count,
                        facet + ":\"" + value + "\"", docs));
            }
        }

        output.add(new GroupFacetResultDTO(gc.getName(), list, gc.getNGroups()));
    }

    return output;
}