internal virtual int calculateEstimation(FullTextQuery query, int nResults)
            {
                switch (query.op)
                {
                case FullTextQuery.Operator.And:
                case FullTextQuery.Operator.Near:
                {
                    int left  = calculateEstimation(((FullTextQueryBinaryOp)query).left, nResults);
                    int right = calculateEstimation(((FullTextQueryBinaryOp)query).right, nResults);
                    return(left < right ? left : right);
                }

                case FullTextQuery.Operator.Or:
                {
                    int left  = calculateEstimation(((FullTextQueryBinaryOp)query).left, nResults);
                    int right = calculateEstimation(((FullTextQueryBinaryOp)query).right, nResults);
                    return(left > right ? left : right);
                }

                case FullTextQuery.Operator.Match:
                case FullTextQuery.Operator.StrictMatch:
                {
                    KeywordList kwd = kwds[((FullTextQueryMatchOp)query).wno];
                    if (kwd.currDoc == 0)
                    {
                        return(0);
                    }
                    else
                    {
                        int curr       = kwd.currDoc;
                        int first      = kwd.list.FirstKey;
                        int last       = kwd.list.LastKey;
                        int estimation = nResults * (last - first + 1) / (curr - first + 1);
                        if (estimation > kwd.list.Count)
                        {
                            estimation = kwd.list.Count;
                        }
                        return(estimation);
                    }
                }

                case FullTextQuery.Operator.Not:
                    return(impl.documents.Count);
                }
                return(0);
            }
            internal virtual int calculateWeight(FullTextQuery query)
            {
                switch (query.op)
                {
                case FullTextQuery.Operator.And:
                {
                    return(calculateWeight(((FullTextQueryBinaryOp)query).left));
                }

                case FullTextQuery.Operator.Near:
                {
                    int shift = STRICT_MATCH_BONUS;
                    for (FullTextQuery q = ((FullTextQueryBinaryOp)query).right; q.op == FullTextQuery.Operator.Near; q = ((FullTextQueryBinaryOp)q).right)
                    {
                        shift += STRICT_MATCH_BONUS;
                    }
                    return(shift >= 32 ? 0 : (calculateWeight(((FullTextQueryBinaryOp)query).left) >> shift));
                }

                case FullTextQuery.Operator.Or:
                {
                    int leftWeight  = calculateWeight(((FullTextQueryBinaryOp)query).left);
                    int rightWeight = calculateWeight(((FullTextQueryBinaryOp)query).right);
                    return(leftWeight > rightWeight ? leftWeight : rightWeight);
                }

                case FullTextQuery.Operator.Match:
                case FullTextQuery.Operator.StrictMatch:
                {
                    int wno = ((FullTextQueryMatchOp)query).wno;
                    return(kwds[wno].list == null ? 0 : kwds[wno].list.Count);
                }

                default:
                    return(int.MaxValue);
                }
            }
        private QueryBase GetQuery(QueryInfo qi)
        {
            if (String.IsNullOrEmpty(qi.SearchString) ||
                String.IsNullOrEmpty(qi.FieldName) ||
                Index == null)
            {
                return null;
            }

            QueryBase query = null;

            switch (qi.QueryType)
            {
                case "FieldQuery":
                    query = new FieldQuery(qi.FieldName, qi.SearchString);
                    break;

                default:
                    query = new FullTextQuery(qi.SearchString);
                    break;
            }

            return query;
        }
Example #4
0
        private QueryBase GetQuery(QueryInfo qi)
        {
            if (String.IsNullOrEmpty(qi.SearchString) ||
                String.IsNullOrEmpty(qi.FieldName) ||
                Index == null)
            {
                return(null);
            }

            QueryBase query = null;

            switch (qi.QueryType)
            {
            case "FieldQuery":
                query = new FieldQuery(qi.FieldName, qi.SearchString);
                break;

            default:
                query = new FullTextQuery(qi.SearchString);
                break;
            }

            return(query);
        }
 private QueryBase GetQuery()
 {
     QueryBase base2 = null;
     NameValueCollection fieldValues = GetFieldValues();
     string str = StringUtil.GetString(new string[] { Context.ClientPage.ClientRequest.Form["TreeSearch"] });
     if (str == "Search")
     {
         str = string.Empty;
     }
     str = str.Trim();
     if (!string.IsNullOrEmpty(str))
     {
         base2 = new FullTextQuery(str);
     }
     if (fieldValues.Count <= 0)
     {
         return base2;
     }
     CombinedQuery query = new CombinedQuery();
     foreach (string str2 in fieldValues.AllKeys)
     {
         string fieldValue = fieldValues[str2];
         if (fieldValue.Length > 0)
         {
             query.Add(new FieldQuery(str2.ToLowerInvariant(), fieldValue), QueryOccurance.Should);
         }
     }
     return query;
 }
            internal virtual int intersect(int doc, FullTextQuery query)
            {
                int left, right;

                switch (query.op)
                {
                case FullTextQuery.Operator.And:
                case FullTextQuery.Operator.Near:
                    do
                    {
                        left = intersect(doc, ((FullTextQueryBinaryOp)query).left);
                        if (left == int.MaxValue)
                        {
                            return(left);
                        }
                        doc = intersect(left, ((FullTextQueryBinaryOp)query).right);
                    }while (left != doc && doc != int.MaxValue);
                    return(doc);

                case FullTextQuery.Operator.Or:
                    left  = intersect(doc, ((FullTextQueryBinaryOp)query).left);
                    right = intersect(doc, ((FullTextQueryBinaryOp)query).right);
                    return(left < right ? left : right);

                case FullTextQuery.Operator.Match:
                case FullTextQuery.Operator.StrictMatch:
                {
                    KeywordList kwd = kwds[((FullTextQueryMatchOp)query).wno];
                    if (kwd.currDoc >= doc)
                    {
                        return(kwd.currDoc);
                    }
                    IDictionaryEnumerator iterator = kwd.iterator;
                    if (iterator != null)
                    {
                        if (iterator.MoveNext())
                        {
                            DictionaryEntry entry   = iterator.Entry;
                            int             nextDoc = (int)entry.Key;
                            if (nextDoc >= doc)
                            {
                                kwd.currEntry = entry;
                                kwd.currDoc   = nextDoc;
                                return(nextDoc);
                            }
                        }
                        else
                        {
                            kwd.currDoc = 0;
                            return(int.MaxValue);
                        }
                    }
                    if (kwd.list != null)
                    {
                        kwd.iterator = iterator = kwd.list.GetDictionaryEnumerator(doc);
                        if (iterator.MoveNext())
                        {
                            DictionaryEntry entry = iterator.Entry;
                            doc           = (int)entry.Key;
                            kwd.currEntry = entry;
                            kwd.currDoc   = doc;
                            return(doc);
                        }
                    }
                    kwd.currDoc = 0;
                    return(int.MaxValue);
                }

                case FullTextQuery.Operator.Not:
                {
                    int nextDoc = intersect(doc, ((FullTextQueryUnaryOp)query).opd);
                    if (nextDoc == doc)
                    {
                        doc += 1;
                    }
                    return(doc);
                }

                default:
                    return(doc);
                }
            }
            internal virtual FullTextQuery optimize(FullTextQuery query)
            {
                switch (query.op)
                {
                case FullTextQuery.Operator.And:
                case FullTextQuery.Operator.Near:
                {
                    FullTextQuery.Operator op = query.op;
                    int           nConjuncts  = 1;
                    FullTextQuery q           = query;
                    while ((q = ((FullTextQueryBinaryOp)q).right).op == op)
                    {
                        nConjuncts += 1;
                    }
                    ExpressionWeight[] conjuncts = new ExpressionWeight[nConjuncts + 1];
                    q = query;
                    for (int i = 0; i < nConjuncts; i++)
                    {
                        FullTextQueryBinaryOp and = (FullTextQueryBinaryOp)q;
                        conjuncts[i]        = new ExpressionWeight();
                        conjuncts[i].expr   = optimize(and.left);
                        conjuncts[i].weight = calculateWeight(conjuncts[i].expr);
                        q = and.right;
                    }
                    conjuncts[nConjuncts]        = new ExpressionWeight();
                    conjuncts[nConjuncts].expr   = optimize(q);
                    conjuncts[nConjuncts].weight = calculateWeight(conjuncts[nConjuncts].expr);
                    Array.Sort(conjuncts);
                    if (op == FullTextQuery.Operator.And)
                    {
                        // eliminate duplicates
                        int         n = 0, j = -1;
                        InverseList list = null;
                        for (int i = 0; i <= nConjuncts; i++)
                        {
                            q = conjuncts[i].expr;
                            if (q is FullTextQueryMatchOp)
                            {
                                FullTextQueryMatchOp match = (FullTextQueryMatchOp)q;
                                if (n == 0 || kwds[match.wno].list != list)
                                {
                                    j              = match.wno;
                                    list           = kwds[j].list;
                                    conjuncts[n++] = conjuncts[i];
                                }
                                else
                                {
                                    kwds[match.wno].sameAs = j;
                                }
                            }
                            else
                            {
                                conjuncts[n++] = conjuncts[i];
                            }
                        }
                        nConjuncts = n - 1;
                    }
                    else
                    {
                        // calculate distance between keywords
                        int kwdPos = 0;
                        for (int i = 0; i <= nConjuncts; i++)
                        {
                            q = conjuncts[i].expr;
                            if (q is FullTextQueryMatchOp)
                            {
                                FullTextQueryMatchOp match = (FullTextQueryMatchOp)q;
                                kwds[match.wno].kwdOffset = match.pos - kwdPos;
                                kwdPos = match.pos;
                            }
                        }
                    }
                    if (nConjuncts == 0)
                    {
                        return(conjuncts[0].expr);
                    }
                    else
                    {
                        q = query;
                        int i = 0;
                        while (true)
                        {
                            FullTextQueryBinaryOp and = (FullTextQueryBinaryOp)q;
                            and.left = conjuncts[i].expr;
                            if (++i < nConjuncts)
                            {
                                q = and.right;
                            }
                            else
                            {
                                and.right = conjuncts[i].expr;
                                break;
                            }
                        }
                    }
                    break;
                }

                case FullTextQuery.Operator.Or:
                {
                    FullTextQueryBinaryOp or = (FullTextQueryBinaryOp)query;
                    or.left  = optimize(or.left);
                    or.right = optimize(or.right);
                    break;
                }

                case FullTextQuery.Operator.Not:
                {
                    FullTextQueryUnaryOp not = (FullTextQueryUnaryOp)query;
                    not.opd = optimize(not.opd);
                }
                break;

                default:;
                    break;
                }
                return(query);
            }
            internal virtual FullTextSearchResult Search(FullTextQuery query, int maxResults, int timeLimit)
            {
                const int TICKS_PER_MSEC = 10000;

                if (query == null || !query.IsConstrained)
                {
                    return(null);
                }

                long stop = DateTime.Now.Ticks + (long)timeLimit * TICKS_PER_MSEC;

                buildOccurrenceKindWeightTable();
                kwdList = new ArrayList();
                query.Visit(this);
                kwds  = (KeywordList[])kwdList.ToArray(typeof(KeywordList));
                query = optimize(query);
                //Console.WriteLine(query.ToString());
                FullTextSearchHit[] hits = new FullTextSearchHit[maxResults];
                int   currDoc            = 1;
                int   nResults           = 0;
                float nearnessWeight     = impl.helper.NearnessWeight;
                bool  noMoreMatches      = false;

                while (nResults < maxResults && DateTime.Now.Ticks < stop)
                {
                    currDoc = intersect(currDoc, query);
                    if (currDoc == int.MaxValue)
                    {
                        noMoreMatches = true;
                        break;
                    }
                    reset();
                    double kwdRank = evaluate(currDoc, query);
                    if (kwdRank >= 0)
                    {
                        double nearness = calculateNearness();
                        float  rank     = (float)(kwdRank * (1 + calculateNearness() * nearnessWeight));
                        //Console.WriteLine("kwdRank=" + kwdRank + ", nearness=" + nearness + ", total rank=" + rank);
                        hits[nResults++] = new FullTextSearchHit(impl.Storage, currDoc, rank);
                    }
                    currDoc += 1;
                }
                int estimation;

                if (nResults < maxResults)
                {
                    FullTextSearchHit[] realHits = new FullTextSearchHit[nResults];
                    Array.Copy(hits, 0, realHits, 0, nResults);
                    hits = realHits;
                }
                if (noMoreMatches)
                {
                    estimation = nResults;
                }
                else if (query is FullTextQueryMatchOp)
                {
                    estimation = kwds[0].list.Count;
                }
                else
                {
                    estimation = calculateEstimation(query, nResults);
                }
                Array.Sort(hits);
                return(new FullTextSearchResult(hits, estimation));
            }
            internal virtual double evaluate(int doc, FullTextQuery query)
            {
                double left, right;

                switch (query.op)
                {
                case FullTextQuery.Operator.Near:
                case FullTextQuery.Operator.And:
                    left         = evaluate(doc, ((FullTextQueryBinaryOp)query).left);
                    right        = evaluate(doc, ((FullTextQueryBinaryOp)query).right);
                    nOccurrences = 0;
                    return(left < 0 || right < 0 ? -1 : left + right);

                case FullTextQuery.Operator.Or:
                    left  = evaluate(doc, ((FullTextQueryBinaryOp)query).left);
                    right = evaluate(doc, ((FullTextQueryBinaryOp)query).right);
                    return(left > right ? left : right);

                case FullTextQuery.Operator.Match:
                case FullTextQuery.Operator.StrictMatch:
                {
                    KeywordList kwd = kwds[((FullTextQueryMatchOp)query).wno];
                    if (kwd.currDoc != doc)
                    {
                        return(-1);
                    }
                    DocumentOccurrences d = (DocumentOccurrences)kwd.currEntry.Value;
                    int[] occ             = d.occurrences;
                    kwd.occ = occ;
                    int frequency = occ.Length;
                    if (query.op == FullTextQuery.Operator.StrictMatch)
                    {
                        if (nOccurrences == 0)
                        {
                            nOccurrences = frequency;
                            if (occurrences == null || occurrences.Length < frequency)
                            {
                                occurrences = new int[frequency];
                            }
                            for (int i = 0; i < frequency; i++)
                            {
                                occurrences[i] = occ[i] & OCC_POSITION_MASK;
                            }
                        }
                        else
                        {
                            int   nPairs = 0;
                            int[] dst = occurrences;
                            int   occ1 = dst[0];
                            int   occ2 = occ[0] & OCC_POSITION_MASK;
                            int   i = 0, j = 0;
                            int   offs = kwd.kwdOffset;
                            while (true)
                            {
                                if (occ1 + offs <= occ2)
                                {
                                    if (occ1 + offs + 1 >= occ2)
                                    {
                                        dst[nPairs++] = occ2;
                                    }
                                    if (++j == nOccurrences)
                                    {
                                        break;
                                    }
                                    occ1 = dst[j];
                                }
                                else
                                {
                                    if (++i == frequency)
                                    {
                                        break;
                                    }
                                    occ2 = occ[i] & OCC_POSITION_MASK;
                                }
                            }
                            nOccurrences = nPairs;
                            if (nPairs == 0)
                            {
                                return(-1);
                            }
                        }
                    }
                    return(calculateKwdRank(kwd.list, d, occ));
                }

                case FullTextQuery.Operator.Not:
                {
                    double rank = evaluate(doc, ((FullTextQueryUnaryOp)query).opd);
                    return((rank >= 0) ? -1 : 0);
                }

                default:
                    return(-1);
                }
            }