19 using System.Collections.Generic;
22 using Lucene.Net.Search;
23 using Lucene.Net.Index;
24 using Lucene.Net.Support.Compatibility;
25 using TermInfo = Lucene.Net.Search.Vectorhighlight.FieldTermStack.TermInfo;
27 namespace Lucene.Net.Search.Vectorhighlight
35 public HashMap<String, QueryPhraseMap> rootMaps =
new HashMap<String, QueryPhraseMap>();
39 public HashMap<String, List<String>> termSetMap =
new HashMap<String, List<String>>();
41 int termOrPhraseNumber;
45 this.fieldMatch = fieldMatch;
46 Dictionary<Query, Query> flatQueries =
new Dictionary<Query, Query>();
47 flatten(query, flatQueries);
48 SaveTerms(flatQueries);
49 Dictionary<Query, Query> expandQueries = expand(flatQueries);
51 foreach (
Query flatQuery
in expandQueries.Keys)
54 rootMap.
Add(flatQuery);
67 public void flatten(
Query sourceQuery, Dictionary<Query, Query> flatQueries)
75 flatten(clause.
Query, flatQueries);
80 if (!flatQueries.ContainsKey(sourceQuery))
81 flatQueries.Add(sourceQuery, sourceQuery);
86 foreach (
Query query
in dmq)
88 flatten(query, flatQueries);
93 if (!flatQueries.ContainsKey(sourceQuery))
94 flatQueries.Add(sourceQuery, sourceQuery);
98 if (!flatQueries.ContainsKey(sourceQuery))
102 flatQueries.Add(pq, pq);
106 flatQueries.Add(q, q);
113 ISet<Term> terms = SetFactory.CreateHashSet<
Term>();
118 catch (NotSupportedException)
123 foreach (var term
in terms)
125 flatten(
new TermQuery(term), flatQueries);
140 public Dictionary<Query, Query> expand(Dictionary<Query, Query> flatQueries)
142 Dictionary<Query, Query> expandQueries =
new Dictionary<Query, Query>();
143 foreach (
Query query
in new Dictionary<Query, Query>(flatQueries).Keys)
146 flatQueries.Remove(query);
147 expandQueries.Add(query, query);
149 foreach (
Query qj
in flatQueries.Keys)
152 CheckOverlap(expandQueries, (PhraseQuery)query, (PhraseQuery)qj);
155 return expandQueries;
171 CheckOverlap(expandQueries, ats, bts, a.
Slop, a.
Boost);
172 CheckOverlap(expandQueries, bts, ats, b.
Slop, b.
Boost);
188 private void CheckOverlap(Dictionary<Query, Query> expandQueries,
Term[] src,
Term[] dest,
int slop,
float boost)
193 for (
int i = 1; i < src.Length; i++)
196 for (
int j = i; j < src.Length; j++)
198 if ((j - i) < dest.Length && !src[j].
Text.Equals(dest[j - i].
Text))
204 if (overlap && src.Length - i < dest.Length)
207 foreach (
Term srcTerm
in src)
209 for (
int k = src.Length - i; k < dest.Length; k++)
215 if (!expandQueries.ContainsKey(pq))
216 expandQueries.Add(pq, pq);
223 String key = GetKey(query);
228 rootMaps.Put(key, map);
237 private String GetKey(
Query query)
239 if (!fieldMatch)
return null;
241 return ((TermQuery)query).Term.Field;
244 return ((PrefixQuery)query).Prefix.Field;
250 return terms[0].
Field;
253 throw new ApplicationException(
"query \"" + query +
"\" must be flatten first.");
278 void SaveTerms(Dictionary<Query, Query> flatQueries)
280 foreach (
Query query
in flatQueries.Keys)
282 List<String> termSet = GetTermSet(query);
283 if (query is TermQuery)
284 termSet.Add(((TermQuery)query).
Term.
Text);
285 else if (query is PrefixQuery)
286 termSet.Add(((PrefixQuery)query).Prefix.Text +
"*");
287 else if (query is PhraseQuery)
289 foreach (
Term term
in ((PhraseQuery)query).GetTerms())
290 termSet.Add(term.
Text);
293 throw new System.ApplicationException(
"query \"" + query.
ToString() +
"\" must be flatten first.");
297 private List<String> GetTermSet(
Query query)
299 String key = GetKey(query);
300 List<String>
set = termSetMap.Get(key);
303 set =
new List<String>();
304 termSetMap.Put(key,
set);
309 public List<String> getTermSet(String field)
311 return termSetMap.Get(fieldMatch ? field : null);
323 return rootMap == null ? null : RetrieveQueryFromSubMap(rootMap, term);
328 foreach (var kvp
in rootMap.subMap)
330 if (StringUtils.TermStringMatch(kvp.Key, term))
342 public QueryPhraseMap SearchPhrase(String fieldName, List<TermInfo> phraseCandidate)
345 if (root == null)
return null;
351 return rootMaps.Get(fieldMatch ? fieldName : null);
354 int NextTermOrPhraseNumber()
356 return termOrPhraseNumber++;
365 int termOrPhraseNumber;
367 public HashMap<String, QueryPhraseMap> subMap =
new HashMap<String, QueryPhraseMap>();
371 this.fieldQuery = fieldQuery;
374 public void AddTerm(String termText,
float boost)
377 map.MarkTerminal(boost);
380 private QueryPhraseMap GetOrNewMap(HashMap<String, QueryPhraseMap> subMap, String term)
386 subMap.Put(term, map);
393 if (query is TermQuery)
397 else if (query is PrefixQuery)
399 AddTerm(((PrefixQuery)query).Prefix.Text +
"*", query.
Boost);
401 else if (query is PhraseQuery)
405 HashMap<String, QueryPhraseMap> map = subMap;
407 foreach (
Term term
in terms)
409 qpm = GetOrNewMap(map, term.
Text);
415 throw new ApplicationException(
"query \"" + query.
ToString() +
"\" must be flatten first.");
420 return subMap.Get(term);
423 private void MarkTerminal(
float boost)
425 MarkTerminal(0, boost);
428 private void MarkTerminal(
int slop,
float boost)
430 this.terminal =
true;
433 this.termOrPhraseNumber = fieldQuery.NextTermOrPhraseNumber();
436 public bool IsTerminal
438 get {
return terminal; }
448 get {
return boost; }
451 public int TermOrPhraseNumber
453 get {
return termOrPhraseNumber; }
459 foreach (
TermInfo ti
in phraseCandidate)
461 currMap = currMap.
subMap[ti.Text];
462 if (currMap == null)
return null;
464 return currMap.IsValidTermOrPhrase(phraseCandidate) ? currMap : null;
467 public bool IsValidTermOrPhrase(List<TermInfo> phraseCandidate)
470 if (!terminal)
return false;
473 if (phraseCandidate.Count == 1)
return true;
478 int pos = phraseCandidate[0].Position;
479 for (
int i = 1; i < phraseCandidate.Count; i++)
481 int nextPos = phraseCandidate[i].Position;
482 if (Math.Abs(nextPos - pos - 1) > slop)
return false;