static void ProcessBooleanClause(BooleanQuery bq, BooleanClause bc)
 {
     BooleanQuery query = new BooleanQuery();
     foreach (QueryClause clause in bc.Children)
     {
         ProcessClause(query, clause);
     }
     bq.Add(
         query,
         Translate(bc.Type)
         );
 }
 public virtual void TestNoPayload()
 {
     PayloadTermQuery q1 = new PayloadTermQuery(new Term(PayloadHelper.NO_PAYLOAD_FIELD, "zero"), new MaxPayloadFunction());
     PayloadTermQuery q2 = new PayloadTermQuery(new Term(PayloadHelper.NO_PAYLOAD_FIELD, "foo"), new MaxPayloadFunction());
     BooleanClause c1 = new BooleanClause(q1, BooleanClause.Occur.MUST);
     BooleanClause c2 = new BooleanClause(q2, BooleanClause.Occur.MUST_NOT);
     BooleanQuery query = new BooleanQuery();
     query.Add(c1);
     query.Add(c2);
     TopDocs hits = Searcher.Search(query, null, 100);
     Assert.IsTrue(hits != null, "hits is null and it shouldn't be");
     Assert.IsTrue(hits.TotalHits == 1, "hits Size: " + hits.TotalHits + " is not: " + 1);
     int[] results = new int[1];
     results[0] = 0; //hits.ScoreDocs[0].Doc;
     CheckHits.CheckHitCollector(Random(), query, PayloadHelper.NO_PAYLOAD_FIELD, Searcher, results);
 }
Example #3
0
        public override Query Rewrite(IndexReader r)
        {
            if (!query.Clauses.Any())
            {
                return(new MatchAllDocsQuery());
            }

            IList <Filter>        filters = new List <Filter>();
            IList <Query>         queries = new List <Query>();
            IList <BooleanClause> clauses = query.Clauses;
            Query baseQuery;
            int   startIndex;

            if (drillDownDims.Count == query.Clauses.Count())
            {
                baseQuery  = new MatchAllDocsQuery();
                startIndex = 0;
            }
            else
            {
                baseQuery  = clauses[0].Query;
                startIndex = 1;
            }

            for (int i = startIndex; i < clauses.Count; i++)
            {
                BooleanClause clause      = clauses[i];
                Query         queryClause = clause.Query;
                Filter        filter      = GetFilter(queryClause);
                if (filter != null)
                {
                    filters.Add(filter);
                }
                else
                {
                    queries.Add(queryClause);
                }
            }

            if (filters.Count == 0)
            {
                return(query);
            }
            else
            {
                // Wrap all filters using FilteredQuery

                // TODO: this is hackish; we need to do it because
                // BooleanQuery can't be trusted to handle the
                // "expensive filter" case.  Really, each Filter should
                // know its cost and we should take that more
                // carefully into account when picking the right
                // strategy/optimization:
                Query wrapped;
                if (queries.Count == 0)
                {
                    wrapped = baseQuery;
                }
                else
                {
                    // disable coord
                    BooleanQuery wrappedBQ = new BooleanQuery(true);
                    if ((baseQuery is MatchAllDocsQuery) == false)
                    {
                        wrappedBQ.Add(baseQuery, Occur.MUST);
                    }
                    foreach (Query q in queries)
                    {
                        wrappedBQ.Add(q, Occur.MUST);
                    }
                    wrapped = wrappedBQ;
                }

                foreach (Filter filter in filters)
                {
                    wrapped = new FilteredQuery(wrapped, filter, FilteredQuery.QUERY_FIRST_FILTER_STRATEGY);
                }

                return(wrapped);
            }
        }
Example #4
0
        protected internal virtual void AddClause(IList <BooleanClause> clauses, int conj, int mods, Query q)
        {
            bool required, prohibited;

            // If this term is introduced by AND, make the preceding term required,
            // unless it's already prohibited
            if (clauses.Count > 0 && conj == CONJ_AND)
            {
                BooleanClause c = clauses[clauses.Count - 1];
                if (!c.IsProhibited)
                {
                    c.Occur = Occur.MUST;
                }
            }

            if (clauses.Count > 0 && DefaultOperator == AND_OPERATOR && conj == CONJ_OR)
            {
                // If this term is introduced by OR, make the preceding term optional,
                // unless it's prohibited (that means we leave -a OR b but +a OR b-->a OR b)
                // notice if the input is a OR b, first term is parsed as required; without
                // this modification a OR b would parsed as +a OR b
                BooleanClause c = clauses[clauses.Count - 1];
                if (!c.IsProhibited)
                {
                    c.Occur = Occur.SHOULD;
                }
            }

            // We might have been passed a null query; the term might have been
            // filtered away by the analyzer.
            if (q == null)
            {
                return;
            }

            if (DefaultOperator == OR_OPERATOR)
            {
                // We set REQUIRED if we're introduced by AND or +; PROHIBITED if
                // introduced by NOT or -; make sure not to set both.
                prohibited = (mods == MOD_NOT);
                required   = (mods == MOD_REQ);
                if (conj == CONJ_AND && !prohibited)
                {
                    required = true;
                }
            }
            else
            {
                // We set PROHIBITED if we're introduced by NOT or -; We set REQUIRED
                // if not PROHIBITED and not introduced by OR
                prohibited = (mods == MOD_NOT);
                required   = (!prohibited && conj != CONJ_OR);
            }
            if (required && !prohibited)
            {
                clauses.Add(NewBooleanClause(q, Occur.MUST));
            }
            else if (!required && !prohibited)
            {
                clauses.Add(NewBooleanClause(q, Occur.SHOULD));
            }
            else if (!required && prohibited)
            {
                clauses.Add(NewBooleanClause(q, Occur.MUST_NOT));
            }
            else
            {
                throw new Exception("Clause cannot be both required and prohibited");
            }
        }
Example #5
0
            public override Scorer GetScorer(AtomicReaderContext context, IBits acceptDocs)
            {
                IList <Scorer> required           = new JCG.List <Scorer>();
                IList <Scorer> prohibited         = new JCG.List <Scorer>();
                IList <Scorer> optional           = new JCG.List <Scorer>();
                IEnumerator <BooleanClause> cIter = outerInstance.clauses.GetEnumerator();

                foreach (Weight w in m_weights)
                {
                    cIter.MoveNext();
                    BooleanClause c         = cIter.Current;
                    Scorer        subScorer = w.GetScorer(context, acceptDocs);
                    if (subScorer == null)
                    {
                        if (c.IsRequired)
                        {
                            return(null);
                        }
                    }
                    else if (c.IsRequired)
                    {
                        required.Add(subScorer);
                    }
                    else if (c.IsProhibited)
                    {
                        prohibited.Add(subScorer);
                    }
                    else
                    {
                        optional.Add(subScorer);
                    }
                }

                if (required.Count == 0 && optional.Count == 0)
                {
                    // no required and optional clauses.
                    return(null);
                }
                else if (optional.Count < outerInstance.m_minNrShouldMatch)
                {
                    // either >1 req scorer, or there are 0 req scorers and at least 1
                    // optional scorer. Therefore if there are not enough optional scorers
                    // no documents will be matched by the query
                    return(null);
                }

                // simple conjunction
                if (optional.Count == 0 && prohibited.Count == 0)
                {
                    float coord = disableCoord ? 1.0f : Coord(required.Count, m_maxCoord);
                    return(new ConjunctionScorer(this, required.ToArray(), coord));
                }

                // simple disjunction
                if (required.Count == 0 && prohibited.Count == 0 && outerInstance.m_minNrShouldMatch <= 1 && optional.Count > 1)
                {
                    var coord = new float[optional.Count + 1];
                    for (int i = 0; i < coord.Length; i++)
                    {
                        coord[i] = disableCoord ? 1.0f : Coord(i, m_maxCoord);
                    }
                    return(new DisjunctionSumScorer(this, optional.ToArray(), coord));
                }

                // Return a BooleanScorer2
                return(new BooleanScorer2(this, disableCoord, outerInstance.m_minNrShouldMatch, required, prohibited, optional, m_maxCoord));
            }
Example #6
0
            public override Explanation Explain(AtomicReaderContext context, int doc)
            {
                int minShouldMatch         = outerInstance.MinimumNumberShouldMatch;
                ComplexExplanation sumExpl = new ComplexExplanation();

                sumExpl.Description = "sum of:";
                int   coord            = 0;
                float sum              = 0.0f;
                bool  fail             = false;
                int   shouldMatchCount = 0;

                using (IEnumerator <BooleanClause> cIter = outerInstance.clauses.GetEnumerator())
                {
                    foreach (Weight w in m_weights)
                    {
                        cIter.MoveNext();
                        BooleanClause c = cIter.Current;
                        if (w.GetScorer(context, context.AtomicReader.LiveDocs) == null)
                        {
                            if (c.IsRequired)
                            {
                                fail = true;
                                Explanation r = new Explanation(0.0f, "no match on required clause (" + c.Query.ToString() + ")");
                                sumExpl.AddDetail(r);
                            }
                            continue;
                        }
                        Explanation e = w.Explain(context, doc);
                        if (e.IsMatch)
                        {
                            if (!c.IsProhibited)
                            {
                                sumExpl.AddDetail(e);
                                sum += e.Value;
                                coord++;
                            }
                            else
                            {
                                Explanation r = new Explanation(0.0f, "match on prohibited clause (" + c.Query.ToString() + ")");
                                r.AddDetail(e);
                                sumExpl.AddDetail(r);
                                fail = true;
                            }
                            if (c.Occur == Occur_e.SHOULD)
                            {
                                shouldMatchCount++;
                            }
                        }
                        else if (c.IsRequired)
                        {
                            Explanation r = new Explanation(0.0f, "no match on required clause (" + c.Query.ToString() + ")");
                            r.AddDetail(e);
                            sumExpl.AddDetail(r);
                            fail = true;
                        }
                    }
                }
                if (fail)
                {
                    sumExpl.Match       = false;
                    sumExpl.Value       = 0.0f;
                    sumExpl.Description = "Failure to meet condition(s) of required/prohibited clause(s)";
                    return(sumExpl);
                }
                else if (shouldMatchCount < minShouldMatch)
                {
                    sumExpl.Match       = false;
                    sumExpl.Value       = 0.0f;
                    sumExpl.Description = "Failure to match minimum number " + "of optional clauses: " + minShouldMatch;
                    return(sumExpl);
                }

                sumExpl.Match = 0 < coord ? true : false;
                sumExpl.Value = sum;

                float coordFactor = disableCoord ? 1.0f : Coord(coord, m_maxCoord);

                if (coordFactor == 1.0f)
                {
                    return(sumExpl); // eliminate wrapper
                }
                else
                {
                    ComplexExplanation result = new ComplexExplanation(sumExpl.IsMatch, sum * coordFactor, "product of:");
                    result.AddDetail(sumExpl);
                    result.AddDetail(new Explanation(coordFactor, "coord(" + coord + "/" + m_maxCoord + ")"));
                    return(result);
                }
            }
        /// <summary>
        ///     Creates the price range query.
        /// </summary>
        /// <param name="priceLists">The price lists.</param>
        /// <param name="index">The index.</param>
        /// <param name="field">The field.</param>
        /// <param name="currency">The currency.</param>
        /// <param name="lowerbound">The lowerbound.</param>
        /// <param name="upperbound">The upperbound.</param>
        /// <param name="lowerboundincluded">
        ///     if set to <c>true</c> [lowerboundincluded].
        /// </param>
        /// <param name="upperboundincluded">
        ///     if set to <c>true</c> [upperboundincluded].
        /// </param>
        /// <returns></returns>
        private static BooleanQuery CreatePriceRangeQuery(
            string[] priceLists,
            int index,
            string field,
            string currency,
            string lowerbound,
            string upperbound,
            bool lowerboundincluded,
            bool upperboundincluded)
        {
            var query = new BooleanQuery();

            // create left part
            var filter =
                new TermRangeFilter(
                    String.Format("{0}_{1}_{2}", field, currency, priceLists[index - 1].ToLower()),
                    "*",
                    "*",
                    true,
                    false);
            var leftClause = new BooleanClause(new ConstantScoreQuery(filter), Occur.MUST_NOT);
            query.Add(leftClause);

            // create right part
            if (index == priceLists.Count()) // last element
            {
                //var rangefilter = NumericRangeFilter.;
                var filter2 =
                    new TermRangeFilter(
                        String.Format("{0}_{1}_{2}", field, currency, priceLists[index - 1].ToLower()),
                        lowerbound,
                        upperbound,
                        lowerboundincluded,
                        upperboundincluded);
                var rightClause = new BooleanClause(new ConstantScoreQuery(filter2), Occur.MUST);
                query.Add(rightClause);
            }
            else
            {
                query.Add(
                    CreatePriceRangeQuery(
                        priceLists,
                        index + 1,
                        field,
                        currency,
                        lowerbound,
                        upperbound,
                        lowerboundincluded,
                        upperboundincluded),
                    Occur.SHOULD);
            }

            return query;
        }
Example #8
0
 public override BooleanClause VisitBooleanClause(BooleanClause clause)
 {
     _text.Append(clause.GetOccur());
     return(base.VisitBooleanClause(clause));
 }
Example #9
0
        /// <summary>
        /// Searches the specified query.
        /// </summary>
        /// <param name="query">The query.</param>
        /// <param name="searchType">Type of the search.</param>
        /// <param name="entities">The entities.</param>
        /// <param name="fieldCriteria">The field criteria.</param>
        /// <param name="size">The size.</param>
        /// <param name="from">From.</param>
        /// <param name="totalResultsAvailable">The total results available.</param>
        /// <returns></returns>
        public override List <IndexModelBase> Search(string query, SearchType searchType, List <int> entities, SearchFieldCriteria fieldCriteria, int?size, int?from, out long totalResultsAvailable)
        {
            List <IndexModelBase> documents = new List <IndexModelBase>();

            totalResultsAvailable = 0;
            bool allEntities = false;

            BooleanQuery  queryContainer  = new BooleanQuery();
            List <string> combinedFields  = new List <string>();
            List <Type>   indexModelTypes = new List <Type>();
            Dictionary <string, Analyzer> combinedFieldAnalyzers = new Dictionary <string, Analyzer>();

            using (RockContext rockContext = new RockContext())
            {
                var entityTypeService = new EntityTypeService(rockContext);
                if (entities == null || entities.Count == 0)
                {
                    // add all entities
                    allEntities = true;
                    var selectedEntityTypes = EntityTypeCache.All().Where(e => e.IsIndexingSupported && e.IsIndexingEnabled && e.FriendlyName != "Site");

                    foreach (var entityTypeCache in selectedEntityTypes)
                    {
                        entities.Add(entityTypeCache.Id);
                    }
                }

                foreach (var entityId in entities)
                {
                    // get entities search model name
                    var entityType = entityTypeService.GetNoTracking(entityId);
                    indexModelTypes.Add(entityType.IndexModelType);

                    // check if this is a person model, if so we need to add two model types one for person and the other for businesses
                    // wish there was a cleaner way to do this
                    if (entityType.Guid == SystemGuid.EntityType.PERSON.AsGuid())
                    {
                        indexModelTypes.Add(typeof(BusinessIndex));
                    }
                }

                indexModelTypes = indexModelTypes.Distinct().ToList();
            }

            CombineIndexTypes(indexModelTypes, out combinedFields, out combinedFieldAnalyzers);

            var entityFieldFilter = new BooleanQuery();

            if (entities != null && entities.Count != 0 && !allEntities)
            {
                Occur occur = fieldCriteria.SearchType == CriteriaSearchType.And ? Occur.MUST : Occur.SHOULD;
                var   indexModelTypesQuery = new BooleanQuery();

                foreach (var modelType in indexModelTypes)
                {
                    var modelFilter = new BooleanQuery();
                    modelFilter.Add(new TermQuery(new Term("type", modelType.Name.ToLower())), Occur.MUST);

                    if (fieldCriteria != null && fieldCriteria.FieldValues?.Count > 0)
                    {
                        var fieldQuery = new BooleanQuery();
                        foreach (var field in fieldCriteria.FieldValues)
                        {
                            var fieldName = field.Field.Substring(0, 1).ToUpper() + field.Field.Substring(1);

                            if (modelType.GetProperty(fieldName) != null)
                            {
                                // Add field filter
                                var phraseQuery = new PhraseQuery();

                                foreach (var word in field.Value.Split(' '))
                                {
                                    phraseQuery.Add(new Term(fieldName, word.ToLower()));
                                }

                                BooleanClause booleanClause = new BooleanClause(phraseQuery, occur);
                                booleanClause.Query.Boost = field.Boost;
                                fieldQuery.Add(booleanClause);
                            }
                        }

                        if (fieldQuery.Clauses.Count() > 0)
                        {
                            modelFilter.Add(fieldQuery, Occur.MUST);
                        }
                    }

                    indexModelTypesQuery.Add(modelFilter, Occur.SHOULD);
                }

                entityFieldFilter.Add(indexModelTypesQuery, Occur.MUST);

                queryContainer.Add(entityFieldFilter, Occur.MUST);
            }

            switch (searchType)
            {
            case SearchType.ExactMatch:
            {
                var wordQuery = new BooleanQuery();

                if (!string.IsNullOrWhiteSpace(query))
                {
                    var words = query.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                    foreach (var word in words)
                    {
                        var innerQuery = new BooleanQuery();
                        combinedFields.ForEach(f => innerQuery.Add(new PrefixQuery(new Term(f, word.ToLower())), Occur.SHOULD));
                        wordQuery.Add(innerQuery, Occur.SHOULD);
                    }
                }

                if (wordQuery.Count() != 0)
                {
                    queryContainer.Add(wordQuery, Occur.MUST);
                }

                // special logic to support emails
                if (query.Contains("@"))
                {
                    queryContainer.Add(new BooleanClause(new TermQuery(new Term("Email", query)), Occur.SHOULD));
                }

                // special logic to support phone search
                if (query.IsDigitsOnly())
                {
                    queryContainer.Add(new BooleanClause(new WildcardQuery(new Term("PhoneNumbers", "*" + query + "*")), Occur.SHOULD));
                }

                // add a search for all the words as one single search term
                foreach (var field in combinedFields)
                {
                    var phraseQuery = new PhraseQuery();
                    phraseQuery.Add(new Term(field, query.ToLower()));
                    queryContainer.Add(phraseQuery, Occur.SHOULD);
                }

                break;
            }

            case SearchType.Fuzzy:
            {
                foreach (var field in combinedFields)
                {
                    queryContainer.Add(new FuzzyQuery(new Term(field, query.ToLower())), Occur.SHOULD);
                }

                break;
            }

            case SearchType.Wildcard:
            {
                bool enablePhraseSearch = true;

                if (!string.IsNullOrWhiteSpace(query))
                {
                    BooleanQuery wildcardQuery = new BooleanQuery();

                    // break each search term into a separate query and add the * to the end of each
                    var queryTerms = query.Split(' ').Select(p => p.Trim()).ToList();

                    // special logic to support emails
                    if (queryTerms.Count == 1 && query.Contains("@"))
                    {
                        wildcardQuery.Add(new WildcardQuery(new Term("Email", "*" + query.ToLower() + "*")), Occur.SHOULD);
                        enablePhraseSearch = false;
                    }
                    else
                    {
                        foreach (var queryTerm in queryTerms)
                        {
                            if (!string.IsNullOrWhiteSpace(queryTerm))
                            {
                                var innerQuery = new BooleanQuery();
                                combinedFields.ForEach(f => innerQuery.Add(new PrefixQuery(new Term(f, queryTerm.ToLower())), Occur.SHOULD));
                                wildcardQuery.Add(innerQuery, Occur.MUST);
                            }
                        }

                        // add special logic to help boost last names
                        if (queryTerms.Count() > 1 && (indexModelTypes.Contains(typeof(PersonIndex)) || indexModelTypes.Contains(typeof(BusinessIndex))))
                        {
                            BooleanQuery nameQuery = new BooleanQuery
                            {
                                { new PrefixQuery(new Term("FirstName", queryTerms.First().ToLower())), Occur.MUST },
                                { new PrefixQuery(new Term("LastName", queryTerms.Last().ToLower()))
                                  {
                                      Boost = 30
                                  }, Occur.MUST }
                            };
                            wildcardQuery.Add(nameQuery, Occur.SHOULD);

                            nameQuery = new BooleanQuery
                            {
                                { new PrefixQuery(new Term("NickName", queryTerms.First().ToLower())), Occur.MUST },
                                { new PrefixQuery(new Term("LastName", queryTerms.Last().ToLower()))
                                  {
                                      Boost = 30
                                  }, Occur.MUST }
                            };
                            wildcardQuery.Add(nameQuery, Occur.SHOULD);
                        }

                        // special logic to support phone search
                        if (query.IsDigitsOnly())
                        {
                            wildcardQuery.Add(new PrefixQuery(new Term("PhoneNumbers", queryTerms.First().ToLower())), Occur.SHOULD);
                        }
                    }

                    queryContainer.Add(wildcardQuery, Occur.MUST);
                }

                // add a search for all the words as one single search term
                if (enablePhraseSearch)
                {
                    // add a search for all the words as one single search term
                    foreach (var field in combinedFields)
                    {
                        var phraseQuery = new PhraseQuery();
                        phraseQuery.Add(new Term(field, query.ToLower()));
                        queryContainer.Add(phraseQuery, Occur.SHOULD);
                    }
                }

                break;
            }
            }

            int returnSize = 10;

            if (size.HasValue)
            {
                returnSize = size.Value;
            }

            try
            {
                OpenReader();
            }
            catch (IndexNotFoundException)
            {
                // Issue opening index. Most likely cause is the index is empty so return an empty results set.
                return(new List <IndexModelBase>());
            }

            TopDocs topDocs = null;

            if (from.HasValue)
            {
                TopScoreDocCollector collector = TopScoreDocCollector.Create(returnSize * 10, true);   // Search for 10 pages with returnSize entries in each page
                _indexSearcher.Search(queryContainer, collector);
                topDocs = collector.GetTopDocs(from.Value, returnSize);
            }
            else
            {
                topDocs = _indexSearcher.Search(queryContainer, returnSize);
            }

            totalResultsAvailable = topDocs.TotalHits;

            if (topDocs != null)
            {
                foreach (var hit in topDocs.ScoreDocs)
                {
                    var document = LuceneDocToIndexModel(queryContainer, hit);
                    if (document != null)
                    {
                        documents.Add(document);
                    }
                }
            }

            return(documents);
        }
Example #10
0
 public override string ToString()
 {
     return(BooleanClause.ToString(occur) + filter.ToString());
 }
Example #11
0
 public override void Add(BooleanClause clause)
 {
     throw new NotSupportedException();
 }
Example #12
0
        public SingleQueryFilter(BooleanClause clause = BooleanClause.And)
        {
            this.Clause = clause;

            _predicateSet = new HashSet <FieldPredicate>(FieldPredicateComparer);
        }
 /// <summary>
 /// Wrapper to set HasQuery flag
 /// </summary>
 /// <param name="clause"></param>
 internal void QueryAdd(BooleanClause clause)
 {
     this.HasQuery = true;
     this.Query.Add(clause);
 }