blob: 8435bbed82d68b95b9e0e4ea940bfba13ca68808 [file] [log] [blame]
using System.Collections.Generic;
using Lucene.Net.Facet;
namespace Lucene.Net.Facet.Range
{
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using MatchingDocs = FacetsCollector.MatchingDocs;
using FunctionValues = Lucene.Net.Queries.Function.FunctionValues;
using ValueSource = Lucene.Net.Queries.Function.ValueSource;
using LongFieldSource = Lucene.Net.Queries.Function.ValueSources.LongFieldSource;
using DocIdSet = Lucene.Net.Search.DocIdSet;
using Filter = Lucene.Net.Search.Filter;
using Bits = Lucene.Net.Util.Bits;
using DocIdSetIterator = Lucene.Net.Search.DocIdSetIterator;
/// <summary>
/// <seealso cref="Facets"/> implementation that computes counts for
/// dynamic long ranges from a provided <seealso cref="ValueSource"/>,
/// using <seealso cref="FunctionValues#longVal"/>. Use
/// this for dimensions that change in real-time (e.g. a
/// relative time based dimension like "Past day", "Past 2
/// days", etc.) or that change for each request (e.g.
/// distance from the user's location, "< 1 km", "< 2 km",
/// etc.).
///
/// @lucene.experimental
/// </summary>
public class LongRangeFacetCounts : RangeFacetCounts
{
/// <summary>
/// Create {@code LongRangeFacetCounts}, using {@link
/// LongFieldSource} from the specified field.
/// </summary>
public LongRangeFacetCounts(string field, FacetsCollector hits, params LongRange[] ranges)
: this(field, new LongFieldSource(field), hits, ranges)
{
}
/// <summary>
/// Create {@code RangeFacetCounts}, using the provided
/// <seealso cref="ValueSource"/>.
/// </summary>
public LongRangeFacetCounts(string field, ValueSource valueSource, FacetsCollector hits, params LongRange[] ranges)
: this(field, valueSource, hits, null, ranges)
{
}
/// <summary>
/// Create {@code RangeFacetCounts}, using the provided
/// <seealso cref="ValueSource"/>, and using the provided Filter as
/// a fastmatch: only documents passing the filter are
/// checked for the matching ranges. The filter must be
/// random access (implement <seealso cref="DocIdSet#bits"/>).
/// </summary>
public LongRangeFacetCounts(string field, ValueSource valueSource, FacetsCollector hits, Filter fastMatchFilter, params LongRange[] ranges)
: base(field, ranges, fastMatchFilter)
{
Count(valueSource, hits.GetMatchingDocs);
}
private void Count(ValueSource valueSource, IList<MatchingDocs> matchingDocs)
{
LongRange[] ranges = (LongRange[])this.Ranges;
LongRangeCounter counter = new LongRangeCounter(ranges);
int missingCount = 0;
foreach (MatchingDocs hits in matchingDocs)
{
FunctionValues fv = valueSource.GetValues(new Dictionary<string, object>(), hits.context);
TotCount += hits.totalHits;
Bits bits;
if (FastMatchFilter != null)
{
DocIdSet dis = FastMatchFilter.GetDocIdSet(hits.context, null);
if (dis == null)
{
// No documents match
continue;
}
bits = dis.GetBits();
if (bits == null)
{
throw new System.ArgumentException("fastMatchFilter does not implement DocIdSet.bits");
}
}
else
{
bits = null;
}
DocIdSetIterator docs = hits.bits.GetIterator();
int doc;
while ((doc = docs.NextDoc()) != DocIdSetIterator.NO_MORE_DOCS)
{
if (bits != null && bits.Get(doc) == false)
{
doc++;
continue;
}
// Skip missing docs:
if (fv.Exists(doc))
{
counter.add(fv.LongVal(doc));
}
else
{
missingCount++;
}
}
}
int x = counter.fillCounts(Counts);
missingCount += x;
//System.out.println("totCount " + totCount + " missingCount " + counter.missingCount);
TotCount -= missingCount;
}
}
}