blob: 3d7c3cc5b46a7ee898a55193fac7e19d2f4d5e6d [file] [log] [blame]
// Lucene version compatibility level 4.8.1
using Lucene.Net.Index;
using Lucene.Net.Support;
using Lucene.Net.Util;
using System;
using System.Collections.Generic;
namespace Lucene.Net.Facet.SortedSet
{
/*
* 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.
*/
/// <summary>
/// Default implementation of <see cref="SortedSetDocValuesFacetCounts"/>
/// </summary>
public class DefaultSortedSetDocValuesReaderState : SortedSetDocValuesReaderState
{
private readonly string field;
private readonly AtomicReader topReader;
private readonly int valueCount;
/// <summary>
/// <see cref="IndexReader"/> passed to the constructor. </summary>
private readonly IndexReader origReader;
private readonly IDictionary<string, OrdRange> prefixToOrdRange = new Dictionary<string, OrdRange>();
/// <summary>
/// Creates this, pulling doc values from the specified
/// field.
/// </summary>
public DefaultSortedSetDocValuesReaderState(IndexReader reader, string field = FacetsConfig.DEFAULT_INDEX_FIELD_NAME)
{
this.field = field;
this.origReader = reader;
// We need this to create thread-safe MultiSortedSetDV
// per collector:
topReader = SlowCompositeReaderWrapper.Wrap(reader);
SortedSetDocValues dv = topReader.GetSortedSetDocValues(field);
if (dv == null)
{
throw new ArgumentException("field \"" + field + "\" was not indexed with SortedSetDocValues");
}
if (dv.ValueCount > int.MaxValue)
{
throw new ArgumentException("can only handle valueCount < System.Int32.MaxValue; got " + dv.ValueCount);
}
valueCount = (int)dv.ValueCount;
// TODO: we can make this more efficient if eg we can be
// "involved" when IOrdinalMap is being created? Ie see
// each term/ord it's assigning as it goes...
string lastDim = null;
int startOrd = -1;
BytesRef spare = new BytesRef();
// TODO: this approach can work for full hierarchy?;
// TaxoReader can't do this since ords are not in
// "sorted order" ... but we should generalize this to
// support arbitrary hierarchy:
for (int ord = 0; ord < valueCount; ord++)
{
dv.LookupOrd(ord, spare);
string[] components = FacetsConfig.StringToPath(spare.Utf8ToString());
if (components.Length != 2)
{
throw new ArgumentException("this class can only handle 2 level hierarchy (dim/value); got: " + Arrays.ToString(components) + " " + spare.Utf8ToString());
}
if (!components[0].Equals(lastDim, StringComparison.Ordinal))
{
if (lastDim != null)
{
prefixToOrdRange[lastDim] = new OrdRange(startOrd, ord - 1);
}
startOrd = ord;
lastDim = components[0];
}
}
if (lastDim != null)
{
prefixToOrdRange[lastDim] = new OrdRange(startOrd, valueCount - 1);
}
}
/// <summary>
/// Return top-level doc values.
/// </summary>
public override SortedSetDocValues GetDocValues()
{
return topReader.GetSortedSetDocValues(field);
}
/// <summary>
/// Returns mapping from prefix to <see cref="SortedSetDocValuesReaderState.OrdRange"/>.
/// </summary>
public override IDictionary<string, OrdRange> PrefixToOrdRange => prefixToOrdRange;
/// <summary>
/// Returns the <see cref="SortedSetDocValuesReaderState.OrdRange"/> for this dimension.
/// </summary>
public override OrdRange GetOrdRange(string dim)
{
prefixToOrdRange.TryGetValue(dim, out OrdRange result);
return result;
}
/// <summary>
/// Indexed field we are reading.
/// </summary>
public override string Field => field;
public override IndexReader OrigReader => origReader;
/// <summary>
/// Number of unique labels.
/// </summary>
public override int Count => valueCount;
}
}