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; }
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); } }