private void HandleRangeFacet(string index, Facet facet, IndexQuery indexQuery, IndexSearcher currentIndexSearcher, Dictionary <string, IEnumerable <FacetValue> > results)
        {
            var rangeResults = new List <FacetValue>();
            var filter       = indexQuery.GetFilter();

            foreach (var range in facet.Ranges)
            {
                var baseQuery = database.IndexStorage.GetLuceneQuery(index, indexQuery, database.IndexQueryTriggers);
                //TODO the built-in parser can't handle [NULL TO 100.0}, i.e. a mix of [ and }
                //so we need to handle this ourselves (greater and less-than-or-equal)
                var rangeQuery = database.IndexStorage.GetLuceneQuery(index, new IndexQuery
                {
                    Query = facet.Name + ":" + range
                }, database.IndexQueryTriggers);

                var joinedQuery = new BooleanQuery();
                joinedQuery.Add(baseQuery, BooleanClause.Occur.MUST);
                joinedQuery.Add(rangeQuery, BooleanClause.Occur.MUST);

                var topDocs = currentIndexSearcher.Search(joinedQuery, filter, 1);

                if (topDocs.TotalHits > 0)
                {
                    rangeResults.Add(new FacetValue
                    {
                        Count = topDocs.TotalHits,
                        Range = range
                    });
                }
            }

            results[facet.Name] = rangeResults;
        }
        private void HandleTermsFacet(string index, Facet facet, IndexQuery indexQuery, IndexSearcher currentIndexSearcher, Dictionary <string, IEnumerable <FacetValue> > results)
        {
            var terms = database.ExecuteGetTermsQuery(index,
                                                      facet.Name, null,
                                                      database.Configuration.MaxPageSize);
            var termResults = new List <FacetValue>();
            var baseQuery   = database.IndexStorage.GetLuceneQuery(index, indexQuery, database.IndexQueryTriggers);
            var filter      = indexQuery.GetFilter();

            foreach (var term in terms)
            {
                var termQuery = new TermQuery(new Term(facet.Name, term));

                var joinedQuery = new BooleanQuery();
                joinedQuery.Add(baseQuery, BooleanClause.Occur.MUST);
                joinedQuery.Add(termQuery, BooleanClause.Occur.MUST);

                var topDocs = currentIndexSearcher.Search(joinedQuery, filter, 1);

                if (topDocs.TotalHits > 0)
                {
                    termResults.Add(new FacetValue
                    {
                        Count = topDocs.TotalHits,
                        Range = term
                    });
                }
            }

            results[facet.Name] = termResults;
        }
Beispiel #3
0
        private TopDocs ExecuteQuery(IndexSearcher indexSearcher, Query luceneQuery, int start, int pageSize, IndexQuery indexQuery)
        {
            Filter filter = indexQuery.GetFilter();
            Sort   sort   = indexQuery.GetSort(filter, indexDefinition);

            if (pageSize == int.MaxValue)             // we want all docs
            {
                var gatherAllCollector = new GatherAllCollector();
                indexSearcher.Search(luceneQuery, filter, gatherAllCollector);
                return(gatherAllCollector.ToTopDocs());
            }
            // NOTE: We get Start + Pagesize results back so we have something to page on
            if (sort != null)
            {
                return(indexSearcher.Search(luceneQuery, filter, pageSize + start, sort));
            }
            return(indexSearcher.Search(luceneQuery, filter, pageSize + start));
        }
Beispiel #4
0
            public IEnumerable <IndexQueryResult> IntersectionQuery()
            {
                using (IndexStorage.EnsureInvariantCulture())
                {
                    AssertQueryDoesNotContainFieldsThatAreNotIndexes();
                    IndexSearcher indexSearcher;
                    using (parent.GetSearcher(out indexSearcher))
                    {
                        int pageSizeBestGuess           = (indexQuery.Start + indexQuery.PageSize) * 2;
                        int returnedResults             = 0;
                        int skippedResultsInCurrentLoop = 0;
                        int previousIntersectMatches    = 0;

                        var subQueries = indexQuery.Query.Split(new[] { Constants.IntersectSeperator }, StringSplitOptions.RemoveEmptyEntries);
                        if (subQueries.Length <= 1)
                        {
                            throw new InvalidOperationException("Invalid INTRESECT query, must have multiple intersect clauses.");
                        }

                        //Do the first sub-query in the normal way, so that sorting, filtering etc is accounted for
                        var firstSubLuceneQuery = ApplyIndexTriggers(GetLuceneQuery(subQueries[0]));

                        //Not sure how to select the page size here??? The problem is that only docs in this search can be part
                        //of the final result because we're doing an intersection query (but we might exclude some of them)
                        var search = ExecuteQuery(indexSearcher, firstSubLuceneQuery, 0, pageSizeBestGuess, indexQuery);
                        var intersectionCollector = new IntersectionCollector(indexSearcher, search.ScoreDocs);
                        var intersectMatches      = 0;

                        //Keep going until we've pulled through enough intersecting docs to satisfy pageSize + start
                        //OR the current loop doesn't get us any more results, despite increasing the page size
                        do
                        {
                            if (skippedResultsInCurrentLoop > 0)
                            {
                                // We get here because out first attempt didn't get enough docs (after INTERSECTION was calculated)
                                pageSizeBestGuess = pageSizeBestGuess * 2;

                                search = ExecuteQuery(indexSearcher, firstSubLuceneQuery, 0, pageSizeBestGuess, indexQuery);
                                intersectionCollector = new IntersectionCollector(indexSearcher, search.ScoreDocs);
                            }

                            Filter filter = indexQuery.GetFilter();
                            for (int i = 1; i < subQueries.Length; i++)
                            {
                                var luceneSubQuery = ApplyIndexTriggers(GetLuceneQuery(subQueries[i]));
                                indexSearcher.Search(luceneSubQuery, filter, intersectionCollector);
                            }

                            var currentIntersectResults = intersectionCollector.DocumentsIdsForCount(subQueries.Length).ToList();
                            previousIntersectMatches    = intersectMatches;
                            intersectMatches            = currentIntersectResults.Count;
                            skippedResultsInCurrentLoop = pageSizeBestGuess - intersectMatches;
                        } while (previousIntersectMatches < intersectMatches && intersectMatches < indexQuery.PageSize);

                        var intersectResults = intersectionCollector.DocumentsIdsForCount(subQueries.Length).ToList();
                        //It's hard to know what to do here, the TotalHits from the base search isn't really the TotalSize,
                        //because it's before the INTERSECTION has been applied, so only some of those results make it out.
                        //Trying to give an accurate answer is going to be too costly, so we aren't going to try.
                        indexQuery.TotalSize.Value      = search.TotalHits;
                        indexQuery.SkippedResults.Value = skippedResultsInCurrentLoop;

                        //Using the final set of results in the intersectionCollector
                        for (int i = indexQuery.Start; i < intersectResults.Count && (i - indexQuery.Start) < pageSizeBestGuess; i++)
                        {
                            Document         document         = indexSearcher.Doc(intersectResults[i].LuceneId);
                            IndexQueryResult indexQueryResult = parent.RetrieveDocument(document, fieldsToFetch, search.ScoreDocs[i].score);
                            if (ShouldIncludeInResults(indexQueryResult) == false)
                            {
                                indexQuery.SkippedResults.Value++;
                                skippedResultsInCurrentLoop++;
                                continue;
                            }
                            returnedResults++;
                            yield return(indexQueryResult);

                            if (returnedResults == indexQuery.PageSize)
                            {
                                yield break;
                            }
                        }
                    }
                }
            }