Lucene.Net  3.0.3
Lucene.Net is a port of the Lucene search engine library, written in C# and targeted at .NET runtime users.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Pages
PayloadNearQuery.cs
Go to the documentation of this file.
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 using System;
19 
20 using IndexReader = Lucene.Net.Index.IndexReader;
21 using ToStringUtils = Lucene.Net.Util.ToStringUtils;
22 using Explanation = Lucene.Net.Search.Explanation;
23 using Scorer = Lucene.Net.Search.Scorer;
24 using Searcher = Lucene.Net.Search.Searcher;
25 using Similarity = Lucene.Net.Search.Similarity;
26 using Weight = Lucene.Net.Search.Weight;
27 using NearSpansOrdered = Lucene.Net.Search.Spans.NearSpansOrdered;
28 using NearSpansUnordered = Lucene.Net.Search.Spans.NearSpansUnordered;
29 using SpanNearQuery = Lucene.Net.Search.Spans.SpanNearQuery;
30 using SpanQuery = Lucene.Net.Search.Spans.SpanQuery;
31 using SpanScorer = Lucene.Net.Search.Spans.SpanScorer;
32 using SpanWeight = Lucene.Net.Search.Spans.SpanWeight;
33 
34 namespace Lucene.Net.Search.Payloads
35 {
36 
37  /// <summary> This class is very similar to
38  /// <see cref="Lucene.Net.Search.Spans.SpanNearQuery" /> except that it factors
39  /// in the value of the payloads located at each of the positions where the
40  /// <see cref="Lucene.Net.Search.Spans.TermSpans" /> occurs.
41  /// <p/>
42  /// In order to take advantage of this, you must override
43  /// <see cref="Lucene.Net.Search.Similarity.ScorePayload" />
44  /// which returns 1 by default.
45  /// <p/>
46  /// Payload scores are aggregated using a pluggable <see cref="PayloadFunction" />.
47  ///
48  /// </summary>
49  /// <seealso cref="Lucene.Net.Search.Similarity.ScorePayload">
50  /// </seealso>
51  [Serializable]
52  public class PayloadNearQuery:SpanNearQuery, System.ICloneable
53  {
54  protected internal System.String fieldName;
55  protected internal PayloadFunction function;
56 
57  public PayloadNearQuery(SpanQuery[] clauses, int slop, bool inOrder):this(clauses, slop, inOrder, new AveragePayloadFunction())
58  {
59  }
60 
61  public PayloadNearQuery(SpanQuery[] clauses, int slop, bool inOrder, PayloadFunction function):base(clauses, slop, inOrder)
62  {
63  fieldName = clauses[0].Field; // all clauses must have same field
64  this.function = function;
65  }
66 
67  public override Weight CreateWeight(Searcher searcher)
68  {
69  return new PayloadNearSpanWeight(this, this, searcher);
70  }
71 
72  public override System.Object Clone()
73  {
74  int sz = clauses.Count;
75  SpanQuery[] newClauses = new SpanQuery[sz];
76 
77  for (int i = 0; i < sz; i++)
78  {
79  newClauses[i] = clauses[i];
80  }
81  PayloadNearQuery boostingNearQuery = new PayloadNearQuery(newClauses, internalSlop, inOrder);
82  boostingNearQuery.Boost = Boost;
83  return boostingNearQuery;
84  }
85 
86  public override System.String ToString(System.String field)
87  {
88  System.Text.StringBuilder buffer = new System.Text.StringBuilder();
89  buffer.Append("payloadNear([");
90  var i = clauses.GetEnumerator();
91  while (i.MoveNext())
92  {
93  SpanQuery clause = i.Current;
94  buffer.Append(clause.ToString(field));
95  if (i.MoveNext())
96  {
97  buffer.Append(", ");
98  }
99  }
100  buffer.Append("], ");
101  buffer.Append(internalSlop);
102  buffer.Append(", ");
103  buffer.Append(inOrder);
104  buffer.Append(")");
105  buffer.Append(ToStringUtils.Boost(Boost));
106  return buffer.ToString();
107  }
108 
109  // @Override
110  public override int GetHashCode()
111  {
112  int prime = 31;
113  int result = base.GetHashCode();
114  result = prime * result + ((fieldName == null)?0:fieldName.GetHashCode());
115  result = prime * result + ((function == null)?0:function.GetHashCode());
116  return result;
117  }
118 
119  // @Override
120  public override bool Equals(System.Object obj)
121  {
122  if (this == obj)
123  return true;
124  if (!base.Equals(obj))
125  return false;
126  if (GetType() != obj.GetType())
127  return false;
128  PayloadNearQuery other = (PayloadNearQuery) obj;
129  if (fieldName == null)
130  {
131  if (other.fieldName != null)
132  return false;
133  }
134  else if (!fieldName.Equals(other.fieldName))
135  return false;
136  if (function == null)
137  {
138  if (other.function != null)
139  return false;
140  }
141  else if (!function.Equals(other.function))
142  return false;
143  return true;
144  }
145 
146  [Serializable]
148  {
149  private void InitBlock(PayloadNearQuery enclosingInstance)
150  {
151  this.enclosingInstance = enclosingInstance;
152  }
153  private PayloadNearQuery enclosingInstance;
154  public PayloadNearQuery Enclosing_Instance
155  {
156  get
157  {
158  return enclosingInstance;
159  }
160 
161  }
162  public PayloadNearSpanWeight(PayloadNearQuery enclosingInstance, SpanQuery query, Searcher searcher):base(query, searcher)
163  {
164  InitBlock(enclosingInstance);
165  }
166 
167  public override Scorer Scorer(IndexReader reader, bool scoreDocsInOrder, bool topScorer)
168  {
169  return new PayloadNearSpanScorer(enclosingInstance, internalQuery.GetSpans(reader), this, similarity, reader.Norms(internalQuery.Field));
170  }
171  }
172 
174  {
175  private void InitBlock(PayloadNearQuery enclosingInstance)
176  {
177  this.enclosingInstance = enclosingInstance;
178  similarity = Similarity;
179  }
180  private PayloadNearQuery enclosingInstance;
181  public PayloadNearQuery Enclosing_Instance
182  {
183  get
184  {
185  return enclosingInstance;
186  }
187 
188  }
189  new internal Lucene.Net.Search.Spans.Spans spans;
190 
191  protected internal float payloadScore;
192  private int payloadsSeen;
193  internal Similarity similarity;
194 
195  protected internal PayloadNearSpanScorer(PayloadNearQuery enclosingInstance, Lucene.Net.Search.Spans.Spans spans, Weight weight, Similarity similarity, byte[] norms):base(spans, weight, similarity, norms)
196  {
197  InitBlock(enclosingInstance);
198  this.spans = spans;
199  }
200 
201  // Get the payloads associated with all underlying subspans
202  public virtual void GetPayloads(Lucene.Net.Search.Spans.Spans[] subSpans)
203  {
204  for (int i = 0; i < subSpans.Length; i++)
205  {
206  if (subSpans[i] is NearSpansOrdered)
207  {
208  if (((NearSpansOrdered) subSpans[i]).IsPayloadAvailable())
209  {
210  ProcessPayloads(((NearSpansOrdered) subSpans[i]).GetPayload(), subSpans[i].Start(), subSpans[i].End());
211  }
212  GetPayloads(((NearSpansOrdered) subSpans[i]).GetSubSpans());
213  }
214  else if (subSpans[i] is NearSpansUnordered)
215  {
216  if (((NearSpansUnordered) subSpans[i]).IsPayloadAvailable())
217  {
218  ProcessPayloads(((NearSpansUnordered) subSpans[i]).GetPayload(), subSpans[i].Start(), subSpans[i].End());
219  }
220  GetPayloads(((NearSpansUnordered) subSpans[i]).GetSubSpans());
221  }
222  }
223  }
224 
225  /// <summary> By default, uses the <see cref="PayloadFunction" /> to score the payloads, but
226  /// can be overridden to do other things.
227  ///
228  /// </summary>
229  /// <param name="payLoads">The payloads
230  /// </param>
231  /// <param name="start">The start position of the span being scored
232  /// </param>
233  /// <param name="end">The end position of the span being scored
234  ///
235  /// </param>
236  /// <seealso cref="Spans">
237  /// </seealso>
238  protected internal virtual void ProcessPayloads(System.Collections.Generic.ICollection<byte[]> payLoads, int start, int end)
239  {
240  foreach (byte[] thePayload in payLoads)
241  {
242  payloadScore = Enclosing_Instance.function.CurrentScore(doc, Enclosing_Instance.fieldName, start, end, payloadsSeen, payloadScore, similarity.ScorePayload(doc, Enclosing_Instance.fieldName, spans.Start(), spans.End(), thePayload, 0, thePayload.Length));
243  ++payloadsSeen;
244  }
245  }
246 
247  //
248  public /*protected internal*/ override bool SetFreqCurrentDoc()
249  {
250  if (!more)
251  {
252  return false;
253  }
254  Lucene.Net.Search.Spans.Spans[] spansArr = new Lucene.Net.Search.Spans.Spans[1];
255  spansArr[0] = spans;
256  payloadScore = 0;
257  payloadsSeen = 0;
258  GetPayloads(spansArr);
259  return base.SetFreqCurrentDoc();
260  }
261 
262  public override float Score()
263  {
264 
265  return base.Score() * Enclosing_Instance.function.DocScore(doc, Enclosing_Instance.fieldName, payloadsSeen, payloadScore);
266  }
267 
268  protected internal override Explanation Explain(int doc)
269  {
270  Explanation result = new Explanation();
271  Explanation nonPayloadExpl = base.Explain(doc);
272  result.AddDetail(nonPayloadExpl);
273  Explanation payloadBoost = new Explanation();
274  result.AddDetail(payloadBoost);
275  float avgPayloadScore = (payloadsSeen > 0?(payloadScore / payloadsSeen):1);
276  payloadBoost.Value = avgPayloadScore;
277  payloadBoost.Description = "scorePayload(...)";
278  result.Value = nonPayloadExpl.Value * avgPayloadScore;
279  result.Description = "bnq, product of:";
280  return result;
281  }
282  }
283  }
284 }