Introduced FixedBitSetFilterCache that guarantees to produce a FixedBitSet and does evict based on size or time.

Only when segments are merged away due to merging then entries in this cache are cleaned up.

Nested and parent/child rely on the fact that type filters produce a FixedBitSet, the FixedBitSetFilterCache does this.
Also if nested and parent/child is configured the type filters are eagerly loaded by default via the FixedBitSetFilterCache.

Closes #7037
Closes #7031
This commit is contained in:
Martijn van Groningen 2014-07-25 16:17:48 +02:00
parent 852a1103f3
commit 94eed4ef56
58 changed files with 929 additions and 161 deletions

View File

@ -31,6 +31,7 @@ import org.elasticsearch.index.AbstractIndexComponent;
import org.elasticsearch.index.Index;
import org.elasticsearch.index.cache.docset.DocSetCache;
import org.elasticsearch.index.cache.filter.FilterCache;
import org.elasticsearch.index.cache.fixedbitset.FixedBitSetFilterCache;
import org.elasticsearch.index.cache.query.parser.QueryParserCache;
import org.elasticsearch.index.settings.IndexSettings;
@ -42,15 +43,17 @@ public class IndexCache extends AbstractIndexComponent implements CloseableCompo
private final FilterCache filterCache;
private final QueryParserCache queryParserCache;
private final DocSetCache docSetCache;
private final FixedBitSetFilterCache fixedBitSetFilterCache;
private ClusterService clusterService;
@Inject
public IndexCache(Index index, @IndexSettings Settings indexSettings, FilterCache filterCache, QueryParserCache queryParserCache, DocSetCache docSetCache) {
public IndexCache(Index index, @IndexSettings Settings indexSettings, FilterCache filterCache, QueryParserCache queryParserCache, DocSetCache docSetCache, FixedBitSetFilterCache fixedBitSetFilterCache) {
super(index, indexSettings);
this.filterCache = filterCache;
this.queryParserCache = queryParserCache;
this.docSetCache = docSetCache;
this.fixedBitSetFilterCache = fixedBitSetFilterCache;
}
@Inject(optional = true)
@ -78,6 +81,7 @@ public class IndexCache extends AbstractIndexComponent implements CloseableCompo
filterCache.close();
queryParserCache.close();
docSetCache.clear("close");
fixedBitSetFilterCache.clear("close");
if (clusterService != null) {
clusterService.remove(this);
}
@ -87,6 +91,7 @@ public class IndexCache extends AbstractIndexComponent implements CloseableCompo
filterCache.clear(reason);
queryParserCache.clear();
docSetCache.clear(reason);
fixedBitSetFilterCache.clear(reason);
}
@Override

View File

@ -23,6 +23,7 @@ import org.elasticsearch.common.inject.AbstractModule;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.cache.docset.DocSetCacheModule;
import org.elasticsearch.index.cache.filter.FilterCacheModule;
import org.elasticsearch.index.cache.fixedbitset.FixedBitSetFilterCacheModule;
import org.elasticsearch.index.cache.query.parser.QueryParserCacheModule;
/**
@ -41,6 +42,7 @@ public class IndexCacheModule extends AbstractModule {
new FilterCacheModule(settings).configure(binder());
new QueryParserCacheModule(settings).configure(binder());
new DocSetCacheModule(settings).configure(binder());
new FixedBitSetFilterCacheModule(settings).configure(binder());
bind(IndexCache.class).asEagerSingleton();
}

View File

@ -0,0 +1,37 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch 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.
*/
package org.elasticsearch.index.cache.fixedbitset;
import org.apache.lucene.index.AtomicReaderContext;
import org.apache.lucene.search.Filter;
import org.apache.lucene.util.Bits;
import org.apache.lucene.util.FixedBitSet;
import java.io.IOException;
/**
* A filter that always returns a {@link FixedBitSet}.
*/
public abstract class FixedBitSetFilter extends Filter {
@Override
public abstract FixedBitSet getDocIdSet(AtomicReaderContext context, Bits acceptDocs) throws IOException;
}

View File

@ -0,0 +1,305 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch 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.
*/
package org.elasticsearch.index.cache.fixedbitset;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.RemovalListener;
import com.google.common.cache.RemovalNotification;
import org.apache.lucene.index.AtomicReader;
import org.apache.lucene.index.AtomicReaderContext;
import org.apache.lucene.search.DocIdSet;
import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.Filter;
import org.apache.lucene.util.Bits;
import org.apache.lucene.util.FixedBitSet;
import org.elasticsearch.ExceptionsHelper;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.lucene.SegmentReaderUtils;
import org.elasticsearch.common.lucene.search.NoCacheFilter;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.AbstractIndexComponent;
import org.elasticsearch.index.Index;
import org.elasticsearch.index.mapper.DocumentMapper;
import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.mapper.internal.ParentFieldMapper;
import org.elasticsearch.index.mapper.object.ObjectMapper;
import org.elasticsearch.index.search.nested.NestedDocsFilter;
import org.elasticsearch.index.search.nested.NonNestedDocsFilter;
import org.elasticsearch.index.service.IndexService;
import org.elasticsearch.index.service.InternalIndexService;
import org.elasticsearch.index.settings.IndexSettings;
import org.elasticsearch.index.shard.ShardId;
import org.elasticsearch.index.shard.ShardUtils;
import org.elasticsearch.index.shard.service.IndexShard;
import org.elasticsearch.indices.warmer.IndicesWarmer;
import org.elasticsearch.threadpool.ThreadPool;
import java.io.IOException;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
/**
* This is a cache for {@link FixedBitSet} based filters and is unbounded by size or time.
* <p/>
* Use this cache with care, only components that require that a filter is to be materialized as a {@link FixedBitSet}
* and require that it should always be around should use this cache, otherwise the
* {@link org.elasticsearch.index.cache.filter.FilterCache} should be used instead.
*/
public class FixedBitSetFilterCache extends AbstractIndexComponent implements AtomicReader.CoreClosedListener, RemovalListener<Object, Cache<Filter, FixedBitSetFilterCache.Value>> {
public static final String LOAD_RANDOM_ACCESS_FILTERS_EAGERLY = "index.load_fixed_bitset_filters_eagerly";
private final boolean loadRandomAccessFiltersEagerly;
private final Cache<Object, Cache<Filter, Value>> loadedFilters;
private IndexService indexService;
@Inject
public FixedBitSetFilterCache(Index index, @IndexSettings Settings indexSettings) {
super(index, indexSettings);
this.loadRandomAccessFiltersEagerly = indexSettings.getAsBoolean(LOAD_RANDOM_ACCESS_FILTERS_EAGERLY, true);
this.loadedFilters = CacheBuilder.newBuilder().removalListener(this).build();
}
@Inject(optional = true)
public void setIndicesWarmer(IndicesWarmer indicesWarmer) {
indicesWarmer.addListener(new FixedBitSetFilterWarmer());
}
public FixedBitSetFilter getFixedBitSetFilter(Filter filter) {
assert filter != null;
assert !(filter instanceof NoCacheFilter);
return new FixedBitSetFilterWrapper(filter);
}
@Override
public void onClose(Object ownerCoreCacheKey) {
loadedFilters.invalidate(ownerCoreCacheKey);
}
public void clear(String reason) {
logger.debug("Clearing all FixedBitSets because [{}]", reason);
loadedFilters.invalidateAll();
loadedFilters.cleanUp();
}
private FixedBitSet getAndLoadIfNotPresent(final Filter filter, final AtomicReaderContext context) throws IOException, ExecutionException {
final Object coreCacheReader = context.reader().getCoreCacheKey();
final ShardId shardId = ShardUtils.extractShardId(context.reader());
Cache<Filter, Value> filterToFbs = loadedFilters.get(coreCacheReader, new Callable<Cache<Filter, Value>>() {
@Override
public Cache<Filter, Value> call() throws Exception {
SegmentReaderUtils.registerCoreListener(context.reader(), FixedBitSetFilterCache.this);
return CacheBuilder.newBuilder().build();
}
});
return filterToFbs.get(filter, new Callable<Value>() {
@Override
public Value call() throws Exception {
DocIdSet docIdSet = filter.getDocIdSet(context, null);
final FixedBitSet fixedBitSet;
if (docIdSet instanceof FixedBitSet) {
fixedBitSet = (FixedBitSet) docIdSet;
} else {
fixedBitSet = new FixedBitSet(context.reader().maxDoc());
if (docIdSet != null && docIdSet != DocIdSet.EMPTY) {
DocIdSetIterator iterator = docIdSet.iterator();
if (iterator != null) {
int doc = iterator.nextDoc();
if (doc != DocIdSetIterator.NO_MORE_DOCS) {
do {
fixedBitSet.set(doc);
doc = iterator.nextDoc();
} while (doc != DocIdSetIterator.NO_MORE_DOCS);
}
}
}
}
Value value = new Value(fixedBitSet, shardId);
if (shardId != null) {
IndexShard shard = indexService.shard(shardId.id());
if (shard != null) {
shard.shardFixedBitSetFilterCache().onCached(value.fixedBitSet.ramBytesUsed());
}
}
return value;
}
}).fixedBitSet;
}
public void setIndexService(InternalIndexService indexService) {
this.indexService = indexService;
}
@Override
public void onRemoval(RemovalNotification<Object, Cache<Filter, Value>> notification) {
Object key = notification.getKey();
if (key == null) {
return;
}
Cache<Filter, Value> value = notification.getValue();
if (value == null) {
return;
}
for (Map.Entry<Filter, Value> entry : value.asMap().entrySet()) {
if (entry.getValue().shardId == null) {
continue;
}
IndexShard shard = indexService.shard(entry.getValue().shardId.id());
if (shard != null) {
ShardFixedBitSetFilterCache shardFixedBitSetFilterCache = shard.shardFixedBitSetFilterCache();
shardFixedBitSetFilterCache.onRemoval(entry.getValue().fixedBitSet.ramBytesUsed());
}
// if null then this means the shard has already been removed and the stats are 0 anyway for the shard this key belongs to
}
}
public static final class Value {
final FixedBitSet fixedBitSet;
final ShardId shardId;
public Value(FixedBitSet fixedBitSet, ShardId shardId) {
this.fixedBitSet = fixedBitSet;
this.shardId = shardId;
}
}
final class FixedBitSetFilterWrapper extends FixedBitSetFilter {
final Filter filter;
FixedBitSetFilterWrapper(Filter filter) {
this.filter = filter;
}
@Override
public FixedBitSet getDocIdSet(AtomicReaderContext context, Bits acceptDocs) throws IOException {
try {
return getAndLoadIfNotPresent(filter, context);
} catch (ExecutionException e) {
throw ExceptionsHelper.convertToElastic(e);
}
}
public String toString() {
return "random_access(" + filter + ")";
}
public boolean equals(Object o) {
if (!(o instanceof FixedBitSetFilterWrapper)) return false;
return this.filter.equals(((FixedBitSetFilterWrapper) o).filter);
}
public int hashCode() {
return filter.hashCode() ^ 0x1117BF26;
}
}
final class FixedBitSetFilterWarmer extends IndicesWarmer.Listener {
@Override
public TerminationHandle warmNewReaders(final IndexShard indexShard, IndexMetaData indexMetaData, IndicesWarmer.WarmerContext context, ThreadPool threadPool) {
if (!loadRandomAccessFiltersEagerly) {
return TerminationHandle.NO_WAIT;
}
boolean hasNested = false;
final Set<Filter> warmUp = new HashSet<>();
final MapperService mapperService = indexShard.mapperService();
for (DocumentMapper docMapper : mapperService.docMappers(false)) {
ParentFieldMapper parentFieldMapper = docMapper.parentFieldMapper();
if (parentFieldMapper.active()) {
warmUp.add(docMapper.typeFilter());
DocumentMapper parentDocumentMapper = mapperService.documentMapper(parentFieldMapper.type());
if (parentDocumentMapper != null) {
warmUp.add(parentDocumentMapper.typeFilter());
}
}
if (docMapper.hasNestedObjects()) {
hasNested = true;
for (ObjectMapper objectMapper : docMapper.objectMappers().values()) {
if (objectMapper.nested().isNested()) {
warmUp.add(objectMapper.nestedTypeFilter());
}
}
}
}
if (hasNested) {
warmUp.add(NonNestedDocsFilter.INSTANCE);
warmUp.add(NestedDocsFilter.INSTANCE);
}
final Executor executor = threadPool.executor(executor());
final CountDownLatch latch = new CountDownLatch(context.searcher().reader().leaves().size() * warmUp.size());
for (final AtomicReaderContext ctx : context.searcher().reader().leaves()) {
for (final Filter filterToWarm : warmUp) {
executor.execute(new Runnable() {
@Override
public void run() {
try {
final long start = System.nanoTime();
getAndLoadIfNotPresent(filterToWarm, ctx);
if (indexShard.warmerService().logger().isTraceEnabled()) {
indexShard.warmerService().logger().trace("warmed random access for [{}], took [{}]", filterToWarm, TimeValue.timeValueNanos(System.nanoTime() - start));
}
} catch (Throwable t) {
indexShard.warmerService().logger().warn("failed to load random access for [{}]", t, filterToWarm);
} finally {
latch.countDown();
}
}
});
}
}
return new TerminationHandle() {
@Override
public void awaitTermination() throws InterruptedException {
latch.await();
}
};
}
@Override
public TerminationHandle warmTopReader(IndexShard indexShard, IndexMetaData indexMetaData, IndicesWarmer.WarmerContext context, ThreadPool threadPool) {
return TerminationHandle.NO_WAIT;
}
}
Cache<Object, Cache<Filter, Value>> getLoadedFilters() {
return loadedFilters;
}
}

View File

@ -0,0 +1,39 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch 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.
*/
package org.elasticsearch.index.cache.fixedbitset;
import org.elasticsearch.common.inject.AbstractModule;
import org.elasticsearch.common.settings.Settings;
/**
*/
public class FixedBitSetFilterCacheModule extends AbstractModule {
private final Settings settings;
public FixedBitSetFilterCacheModule(Settings settings) {
this.settings = settings;
}
@Override
protected void configure() {
bind(FixedBitSetFilterCache.class).asEagerSingleton();
}
}

View File

@ -0,0 +1,51 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch 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.
*/
package org.elasticsearch.index.cache.fixedbitset;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.metrics.CounterMetric;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.settings.IndexSettings;
import org.elasticsearch.index.shard.AbstractIndexShardComponent;
import org.elasticsearch.index.shard.ShardId;
/**
*/
public class ShardFixedBitSetFilterCache extends AbstractIndexShardComponent {
private final CounterMetric totalMetric = new CounterMetric();
@Inject
public ShardFixedBitSetFilterCache(ShardId shardId, @IndexSettings Settings indexSettings) {
super(shardId, indexSettings);
}
public void onCached(long sizeInBytes) {
totalMetric.inc(sizeInBytes);
}
public void onRemoval(long sizeInBytes) {
totalMetric.dec(sizeInBytes);
}
public long getMemorySizeInBytes() {
return totalMetric.count();
}
}

View File

@ -0,0 +1,32 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch 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.
*/
package org.elasticsearch.index.cache.fixedbitset;
import org.elasticsearch.common.inject.AbstractModule;
/**
*/
public class ShardFixedBitSetFilterCacheModule extends AbstractModule {
@Override
protected void configure() {
bind(ShardFixedBitSetFilterCache.class).asEagerSingleton();
}
}

View File

@ -40,6 +40,7 @@ public class SegmentsStats implements Streamable, ToXContent {
private long indexWriterMemoryInBytes;
private long indexWriterMaxMemoryInBytes;
private long versionMapMemoryInBytes;
private long fixedBitSetMemoryInBytes;
public SegmentsStats() {
@ -62,6 +63,10 @@ public class SegmentsStats implements Streamable, ToXContent {
this.versionMapMemoryInBytes += versionMapMemoryInBytes;
}
public void addFixedBitSetMemoryInBytes(long fixedBitSetMemoryInBytes) {
this.fixedBitSetMemoryInBytes += fixedBitSetMemoryInBytes;
}
public void add(SegmentsStats mergeStats) {
if (mergeStats == null) {
return;
@ -70,6 +75,7 @@ public class SegmentsStats implements Streamable, ToXContent {
addIndexWriterMemoryInBytes(mergeStats.indexWriterMemoryInBytes);
addIndexWriterMaxMemoryInBytes(mergeStats.indexWriterMaxMemoryInBytes);
addVersionMapMemoryInBytes(mergeStats.versionMapMemoryInBytes);
addFixedBitSetMemoryInBytes(mergeStats.fixedBitSetMemoryInBytes);
}
/**
@ -123,6 +129,17 @@ public class SegmentsStats implements Streamable, ToXContent {
return new ByteSizeValue(versionMapMemoryInBytes);
}
/**
* Estimation of how much the cached fixed bit sets are taking. (which nested and p/c rely on)
*/
public long getFixedBitSetMemoryInBytes() {
return fixedBitSetMemoryInBytes;
}
public ByteSizeValue getFixedBitSetMemory() {
return new ByteSizeValue(fixedBitSetMemoryInBytes);
}
public static SegmentsStats readSegmentsStats(StreamInput in) throws IOException {
SegmentsStats stats = new SegmentsStats();
stats.readFrom(in);
@ -137,6 +154,7 @@ public class SegmentsStats implements Streamable, ToXContent {
builder.byteSizeField(Fields.INDEX_WRITER_MEMORY_IN_BYTES, Fields.INDEX_WRITER_MEMORY, indexWriterMemoryInBytes);
builder.byteSizeField(Fields.INDEX_WRITER_MAX_MEMORY_IN_BYTES, Fields.INDEX_WRITER_MAX_MEMORY, indexWriterMaxMemoryInBytes);
builder.byteSizeField(Fields.VERSION_MAP_MEMORY_IN_BYTES, Fields.VERSION_MAP_MEMORY, versionMapMemoryInBytes);
builder.byteSizeField(Fields.FIXED_BIT_SET_MEMORY_IN_BYTES, Fields.FIXED_BIT_SET, fixedBitSetMemoryInBytes);
builder.endObject();
return builder;
}
@ -152,6 +170,8 @@ public class SegmentsStats implements Streamable, ToXContent {
static final XContentBuilderString INDEX_WRITER_MAX_MEMORY_IN_BYTES = new XContentBuilderString("index_writer_max_memory_in_bytes");
static final XContentBuilderString VERSION_MAP_MEMORY = new XContentBuilderString("version_map_memory");
static final XContentBuilderString VERSION_MAP_MEMORY_IN_BYTES = new XContentBuilderString("version_map_memory_in_bytes");
static final XContentBuilderString FIXED_BIT_SET = new XContentBuilderString("fixed_bit_set");
static final XContentBuilderString FIXED_BIT_SET_MEMORY_IN_BYTES = new XContentBuilderString("fixed_bit_set_memory_in_bytes");
}
@Override
@ -165,6 +185,9 @@ public class SegmentsStats implements Streamable, ToXContent {
if (in.getVersion().onOrAfter(Version.V_1_4_0)) {
indexWriterMaxMemoryInBytes = in.readLong();
}
if (in.getVersion().onOrAfter(Version.V_1_4_0)) {
fixedBitSetMemoryInBytes = in.readLong();
}
}
@Override
@ -178,5 +201,8 @@ public class SegmentsStats implements Streamable, ToXContent {
if (out.getVersion().onOrAfter(Version.V_1_4_0)) {
out.writeLong(indexWriterMaxMemoryInBytes);
}
if (out.getVersion().onOrAfter(Version.V_1_4_0)) {
out.writeLong(fixedBitSetMemoryInBytes);
}
}
}

View File

@ -29,6 +29,7 @@ import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.Index;
import org.elasticsearch.index.IndexComponent;
import org.elasticsearch.index.cache.fixedbitset.FixedBitSetFilter;
import org.elasticsearch.index.fielddata.IndexFieldData.XFieldComparatorSource.Nested;
import org.elasticsearch.index.mapper.FieldMapper;
import org.elasticsearch.index.mapper.MapperService;
@ -127,41 +128,25 @@ public interface IndexFieldData<FD extends AtomicFieldData> extends IndexCompone
* parent + 1, or 0 if there is no previous parent, and R (excluded).
*/
public static class Nested {
private final Filter rootFilter, innerFilter;
private final FixedBitSetFilter rootFilter, innerFilter;
public Nested(Filter rootFilter, Filter innerFilter) {
public Nested(FixedBitSetFilter rootFilter, FixedBitSetFilter innerFilter) {
this.rootFilter = rootFilter;
this.innerFilter = innerFilter;
}
// TODO: nested docs should not be random filters but specialized
// ones that guarantee that you always get a FixedBitSet
@Deprecated
private static FixedBitSet toFixedBitSet(DocIdSet set, int maxDoc) throws IOException {
if (set == null || set instanceof FixedBitSet) {
return (FixedBitSet) set;
} else {
final FixedBitSet fixedBitSet = new FixedBitSet(maxDoc);
final DocIdSetIterator it = set.iterator();
if (it != null) {
fixedBitSet.or(it);
}
return fixedBitSet;
}
}
/**
* Get a {@link FixedBitSet} that matches the root documents.
*/
public FixedBitSet rootDocs(AtomicReaderContext ctx) throws IOException {
return toFixedBitSet(rootFilter.getDocIdSet(ctx, null), ctx.reader().maxDoc());
return rootFilter.getDocIdSet(ctx, null);
}
/**
* Get a {@link FixedBitSet} that matches the inner documents.
*/
public FixedBitSet innerDocs(AtomicReaderContext ctx) throws IOException {
return toFixedBitSet(innerFilter.getDocIdSet(ctx, null), ctx.reader().maxDoc());
return innerFilter.getDocIdSet(ctx, null);
}
}

View File

@ -24,6 +24,7 @@ import org.elasticsearch.common.Strings;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.lucene.search.XFilteredQuery;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.cache.fixedbitset.FixedBitSetFilter;
import org.elasticsearch.index.fielddata.plain.ParentChildIndexFieldData;
import org.elasticsearch.index.mapper.DocumentMapper;
import org.elasticsearch.index.mapper.internal.ParentFieldMapper;
@ -148,12 +149,12 @@ public class HasChildFilterParser implements FilterParser {
throw new QueryParsingException(parseContext.index(), "[has_child] 'max_children' is less than 'min_children'");
}
Filter nonNestedDocsFilter = null;
FixedBitSetFilter nonNestedDocsFilter = null;
if (parentDocMapper.hasNestedObjects()) {
nonNestedDocsFilter = parseContext.cacheFilter(NonNestedDocsFilter.INSTANCE, null);
nonNestedDocsFilter = parseContext.fixedBitSetFilter(NonNestedDocsFilter.INSTANCE);
}
Filter parentFilter = parseContext.cacheFilter(parentDocMapper.typeFilter(), null);
FixedBitSetFilter parentFilter = parseContext.fixedBitSetFilter(parentDocMapper.typeFilter());
ParentChildIndexFieldData parentChildIndexFieldData = parseContext.getForField(parentFieldMapper);
Query childrenQuery;

View File

@ -19,12 +19,12 @@
package org.elasticsearch.index.query;
import org.apache.lucene.search.Filter;
import org.apache.lucene.search.Query;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.lucene.search.XFilteredQuery;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.cache.fixedbitset.FixedBitSetFilter;
import org.elasticsearch.index.fielddata.plain.ParentChildIndexFieldData;
import org.elasticsearch.index.mapper.DocumentMapper;
import org.elasticsearch.index.mapper.internal.ParentFieldMapper;
@ -146,16 +146,16 @@ public class HasChildQueryParser implements QueryParser {
throw new QueryParsingException(parseContext.index(), "[has_child] 'max_children' is less than 'min_children'");
}
Filter nonNestedDocsFilter = null;
FixedBitSetFilter nonNestedDocsFilter = null;
if (parentDocMapper.hasNestedObjects()) {
nonNestedDocsFilter = parseContext.cacheFilter(NonNestedDocsFilter.INSTANCE, null);
nonNestedDocsFilter = parseContext.fixedBitSetFilter(NonNestedDocsFilter.INSTANCE);
}
// wrap the query with type query
innerQuery = new XFilteredQuery(innerQuery, parseContext.cacheFilter(childDocMapper.typeFilter(), null));
Query query;
Filter parentFilter = parseContext.cacheFilter(parentDocMapper.typeFilter(), null);
FixedBitSetFilter parentFilter = parseContext.fixedBitSetFilter(parentDocMapper.typeFilter());
ParentChildIndexFieldData parentChildIndexFieldData = parseContext.getForField(parentFieldMapper);
if (minChildren > 1 || maxChildren > 0 || scoreType != ScoreType.NONE) {
query = new ChildrenQuery(parentChildIndexFieldData, parentType, childType, parentFilter, innerQuery, scoreType, minChildren,

View File

@ -23,6 +23,10 @@ import org.apache.lucene.search.Query;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.cache.fixedbitset.FixedBitSetFilter;
import org.elasticsearch.index.fielddata.plain.ParentChildIndexFieldData;
import org.elasticsearch.index.mapper.DocumentMapper;
import org.elasticsearch.index.mapper.internal.ParentFieldMapper;
import org.elasticsearch.index.query.support.XContentStructure;
import org.elasticsearch.index.search.child.CustomQueryWrappingFilter;

View File

@ -27,6 +27,7 @@ import org.elasticsearch.common.lucene.search.NotFilter;
import org.elasticsearch.common.lucene.search.XBooleanFilter;
import org.elasticsearch.common.lucene.search.XFilteredQuery;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.cache.fixedbitset.FixedBitSetFilter;
import org.elasticsearch.index.fielddata.plain.ParentChildIndexFieldData;
import org.elasticsearch.index.mapper.DocumentMapper;
import org.elasticsearch.index.mapper.internal.ParentFieldMapper;
@ -164,15 +165,14 @@ public class HasParentQueryParser implements QueryParser {
if (parentTypes.size() == 1) {
DocumentMapper documentMapper = parseContext.mapperService().documentMapper(parentTypes.iterator().next());
if (documentMapper != null) {
parentFilter = parseContext.cacheFilter(documentMapper.typeFilter(), null);
parentFilter = documentMapper.typeFilter();
}
} else {
XBooleanFilter parentsFilter = new XBooleanFilter();
for (String parentTypeStr : parentTypes) {
DocumentMapper documentMapper = parseContext.mapperService().documentMapper(parentTypeStr);
if (documentMapper != null) {
Filter filter = parseContext.cacheFilter(documentMapper.typeFilter(), null);
parentsFilter.add(filter, BooleanClause.Occur.SHOULD);
parentsFilter.add(documentMapper.typeFilter(), BooleanClause.Occur.SHOULD);
}
}
parentFilter = parentsFilter;
@ -182,7 +182,7 @@ public class HasParentQueryParser implements QueryParser {
return null;
}
Filter childrenFilter = parseContext.cacheFilter(new NotFilter(parentFilter), null);
FixedBitSetFilter childrenFilter = parseContext.fixedBitSetFilter(new NotFilter(parentFilter));
if (score) {
return new ParentQuery(parentChildIndexFieldData, innerQuery, parentType, childrenFilter);
} else {

View File

@ -38,6 +38,7 @@ import org.elasticsearch.index.Index;
import org.elasticsearch.index.analysis.AnalysisService;
import org.elasticsearch.index.cache.IndexCache;
import org.elasticsearch.index.engine.IndexEngine;
import org.elasticsearch.index.cache.fixedbitset.FixedBitSetFilterCache;
import org.elasticsearch.index.fielddata.IndexFieldDataService;
import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.mapper.internal.AllFieldMapper;
@ -84,6 +85,8 @@ public class IndexQueryParserService extends AbstractIndexComponent {
final IndexFieldDataService fieldDataService;
final FixedBitSetFilterCache fixedBitSetFilterCache;
final IndexEngine indexEngine;
private final Map<String, QueryParser> queryParsers;
@ -98,7 +101,8 @@ public class IndexQueryParserService extends AbstractIndexComponent {
public IndexQueryParserService(Index index, @IndexSettings Settings indexSettings,
IndicesQueriesRegistry indicesQueriesRegistry,
ScriptService scriptService, AnalysisService analysisService,
MapperService mapperService, IndexCache indexCache, IndexFieldDataService fieldDataService, IndexEngine indexEngine,
MapperService mapperService, IndexCache indexCache, IndexFieldDataService fieldDataService,
IndexEngine indexEngine, FixedBitSetFilterCache fixedBitSetFilterCache,
@Nullable SimilarityService similarityService,
@Nullable Map<String, QueryParserFactory> namedQueryParsers,
@Nullable Map<String, FilterParserFactory> namedFilterParsers) {
@ -110,6 +114,7 @@ public class IndexQueryParserService extends AbstractIndexComponent {
this.indexCache = indexCache;
this.fieldDataService = fieldDataService;
this.indexEngine = indexEngine;
this.fixedBitSetFilterCache = fixedBitSetFilterCache;
this.defaultField = indexSettings.get("index.query.default_field", AllFieldMapper.NAME);
this.queryStringLenient = indexSettings.getAsBoolean("index.query_string.lenient", false);

View File

@ -21,7 +21,6 @@ package org.elasticsearch.index.query;
import org.apache.lucene.search.Filter;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.join.FixedBitSetCachingWrapperFilter;
import org.apache.lucene.search.join.ScoreMode;
import org.apache.lucene.search.join.ToParentBlockJoinQuery;
import org.elasticsearch.common.Strings;
@ -144,11 +143,10 @@ public class NestedFilterParser implements FilterParser {
// // filter based on the type...
// parentFilter = mapper.docMapper().typeFilter();
//}
parentFilter = parseContext.cacheFilter(parentFilter, null);
}
// if the filter cache is disabled, then we still have a filter that is not cached while ToParentBlockJoinQuery
// expects FixedBitSet instances
parentFilter = new FixedBitSetCachingWrapperFilter(parentFilter);
parentFilter = parseContext.fixedBitSetFilter(parentFilter);
Filter nestedFilter = Queries.wrap(new ToParentBlockJoinQuery(query, parentFilter, ScoreMode.None));

View File

@ -23,7 +23,6 @@ import org.apache.lucene.index.AtomicReaderContext;
import org.apache.lucene.search.DocIdSet;
import org.apache.lucene.search.Filter;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.join.FixedBitSetCachingWrapperFilter;
import org.apache.lucene.search.join.ScoreMode;
import org.apache.lucene.search.join.ToParentBlockJoinQuery;
import org.apache.lucene.util.Bits;
@ -151,12 +150,8 @@ public class NestedQueryParser implements QueryParser {
// // filter based on the type...
// parentFilter = mapper.docMapper().typeFilter();
//}
parentFilter = parseContext.cacheFilter(parentFilter, null);
}
// if the filter cache is disabled, then we still have a filter that is not cached while ToParentBlockJoinQuery
// expects FixedBitSet instances
parentFilter = new FixedBitSetCachingWrapperFilter(parentFilter);
parentFilter = parseContext.fixedBitSetFilter(parentFilter);
ToParentBlockJoinQuery joinQuery = new ToParentBlockJoinQuery(query, parentFilter, scoreMode);
joinQuery.setBoost(boost);
if (queryName != null) {

View File

@ -36,6 +36,7 @@ import org.elasticsearch.index.analysis.AnalysisService;
import org.elasticsearch.index.cache.filter.support.CacheKeyFilter;
import org.elasticsearch.index.cache.query.parser.QueryParserCache;
import org.elasticsearch.index.engine.IndexEngine;
import org.elasticsearch.index.cache.fixedbitset.FixedBitSetFilter;
import org.elasticsearch.index.fielddata.IndexFieldData;
import org.elasticsearch.index.mapper.FieldMapper;
import org.elasticsearch.index.mapper.FieldMappers;
@ -169,6 +170,10 @@ public class QueryParseContext {
return queryParser;
}
public FixedBitSetFilter fixedBitSetFilter(Filter filter) {
return indexQueryParser.fixedBitSetFilterCache.getFixedBitSetFilter(filter);
}
public Filter cacheFilter(Filter filter, @Nullable CacheKeyFilter.Key cacheKey) {
if (filter == null) {
return null;

View File

@ -18,12 +18,12 @@
*/
package org.elasticsearch.index.query;
import org.apache.lucene.search.Filter;
import org.apache.lucene.search.Query;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.lucene.search.XFilteredQuery;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.cache.fixedbitset.FixedBitSetFilter;
import org.elasticsearch.index.fielddata.plain.ParentChildIndexFieldData;
import org.elasticsearch.index.mapper.DocumentMapper;
import org.elasticsearch.index.mapper.internal.ParentFieldMapper;
@ -126,9 +126,9 @@ public class TopChildrenQueryParser implements QueryParser {
}
String parentType = childDocMapper.parentFieldMapper().type();
Filter nonNestedDocsFilter = null;
FixedBitSetFilter nonNestedDocsFilter = null;
if (childDocMapper.hasNestedObjects()) {
nonNestedDocsFilter = parseContext.cacheFilter(NonNestedDocsFilter.INSTANCE, null);
nonNestedDocsFilter = parseContext.fixedBitSetFilter(NonNestedDocsFilter.INSTANCE);
}
innerQuery.setBoost(boost);

View File

@ -30,6 +30,7 @@ import org.elasticsearch.common.lucene.docset.DocIdSets;
import org.elasticsearch.common.lucene.search.ApplyAcceptedDocsFilter;
import org.elasticsearch.common.lucene.search.NoopCollector;
import org.elasticsearch.common.lucene.search.Queries;
import org.elasticsearch.index.cache.fixedbitset.FixedBitSetFilter;
import org.elasticsearch.index.fielddata.AtomicParentChildFieldData;
import org.elasticsearch.index.fielddata.IndexParentChildFieldData;
import org.elasticsearch.search.internal.SearchContext;
@ -47,14 +48,14 @@ public class ChildrenConstantScoreQuery extends Query {
private Query originalChildQuery;
private final String parentType;
private final String childType;
private final Filter parentFilter;
private final FixedBitSetFilter parentFilter;
private final int shortCircuitParentDocSet;
private final Filter nonNestedDocsFilter;
private final FixedBitSetFilter nonNestedDocsFilter;
private Query rewrittenChildQuery;
private IndexReader rewriteIndexReader;
public ChildrenConstantScoreQuery(IndexParentChildFieldData parentChildIndexFieldData, Query childQuery, String parentType, String childType, Filter parentFilter, int shortCircuitParentDocSet, Filter nonNestedDocsFilter) {
public ChildrenConstantScoreQuery(IndexParentChildFieldData parentChildIndexFieldData, Query childQuery, String parentType, String childType, FixedBitSetFilter parentFilter, int shortCircuitParentDocSet, FixedBitSetFilter nonNestedDocsFilter) {
this.parentChildIndexFieldData = parentChildIndexFieldData;
this.parentFilter = parentFilter;
this.parentType = parentType;

View File

@ -36,6 +36,7 @@ import org.elasticsearch.common.util.BigArrays;
import org.elasticsearch.common.util.FloatArray;
import org.elasticsearch.common.util.IntArray;
import org.elasticsearch.common.util.LongHash;
import org.elasticsearch.index.cache.fixedbitset.FixedBitSetFilter;
import org.elasticsearch.index.fielddata.IndexParentChildFieldData;
import org.elasticsearch.index.fielddata.plain.ParentChildIndexFieldData;
import org.elasticsearch.search.internal.SearchContext;
@ -58,18 +59,18 @@ public class ChildrenQuery extends Query {
protected final ParentChildIndexFieldData ifd;
protected final String parentType;
protected final String childType;
protected final Filter parentFilter;
protected final FixedBitSetFilter parentFilter;
protected final ScoreType scoreType;
protected Query originalChildQuery;
protected final int minChildren;
protected final int maxChildren;
protected final int shortCircuitParentDocSet;
protected final Filter nonNestedDocsFilter;
protected final FixedBitSetFilter nonNestedDocsFilter;
protected Query rewrittenChildQuery;
protected IndexReader rewriteIndexReader;
public ChildrenQuery(ParentChildIndexFieldData ifd, String parentType, String childType, Filter parentFilter, Query childQuery, ScoreType scoreType, int minChildren, int maxChildren, int shortCircuitParentDocSet, Filter nonNestedDocsFilter) {
public ChildrenQuery(ParentChildIndexFieldData ifd, String parentType, String childType, FixedBitSetFilter parentFilter, Query childQuery, ScoreType scoreType, int minChildren, int maxChildren, int shortCircuitParentDocSet, FixedBitSetFilter nonNestedDocsFilter) {
this.ifd = ifd;
this.parentType = parentType;
this.childType = childType;

View File

@ -29,6 +29,7 @@ import org.elasticsearch.common.lucene.docset.DocIdSets;
import org.elasticsearch.common.lucene.search.ApplyAcceptedDocsFilter;
import org.elasticsearch.common.lucene.search.NoopCollector;
import org.elasticsearch.common.lucene.search.Queries;
import org.elasticsearch.index.cache.fixedbitset.FixedBitSetFilter;
import org.elasticsearch.index.fielddata.AtomicParentChildFieldData;
import org.elasticsearch.index.fielddata.IndexParentChildFieldData;
import org.elasticsearch.index.fielddata.plain.ParentChildIndexFieldData;
@ -45,12 +46,12 @@ public class ParentConstantScoreQuery extends Query {
private final ParentChildIndexFieldData parentChildIndexFieldData;
private Query originalParentQuery;
private final String parentType;
private final Filter childrenFilter;
private final FixedBitSetFilter childrenFilter;
private Query rewrittenParentQuery;
private IndexReader rewriteIndexReader;
public ParentConstantScoreQuery(ParentChildIndexFieldData parentChildIndexFieldData, Query parentQuery, String parentType, Filter childrenFilter) {
public ParentConstantScoreQuery(ParentChildIndexFieldData parentChildIndexFieldData, Query parentQuery, String parentType, FixedBitSetFilter childrenFilter) {
this.parentChildIndexFieldData = parentChildIndexFieldData;
this.originalParentQuery = parentQuery;
this.parentType = parentType;

View File

@ -32,6 +32,7 @@ import org.elasticsearch.common.lucene.search.Queries;
import org.elasticsearch.common.util.BigArrays;
import org.elasticsearch.common.util.FloatArray;
import org.elasticsearch.common.util.LongHash;
import org.elasticsearch.index.cache.fixedbitset.FixedBitSetFilter;
import org.elasticsearch.index.fielddata.IndexParentChildFieldData;
import org.elasticsearch.index.fielddata.plain.ParentChildIndexFieldData;
import org.elasticsearch.search.internal.SearchContext;
@ -50,12 +51,12 @@ public class ParentQuery extends Query {
private final ParentChildIndexFieldData parentChildIndexFieldData;
private Query originalParentQuery;
private final String parentType;
private final Filter childrenFilter;
private final FixedBitSetFilter childrenFilter;
private Query rewrittenParentQuery;
private IndexReader rewriteIndexReader;
public ParentQuery(ParentChildIndexFieldData parentChildIndexFieldData, Query parentQuery, String parentType, Filter childrenFilter) {
public ParentQuery(ParentChildIndexFieldData parentChildIndexFieldData, Query parentQuery, String parentType, FixedBitSetFilter childrenFilter) {
this.parentChildIndexFieldData = parentChildIndexFieldData;
this.originalParentQuery = parentQuery;
this.parentType = parentType;

View File

@ -30,6 +30,7 @@ import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.ElasticsearchIllegalStateException;
import org.elasticsearch.common.lease.Releasable;
import org.elasticsearch.common.lucene.search.EmptyScorer;
import org.elasticsearch.index.cache.fixedbitset.FixedBitSetFilter;
import org.elasticsearch.index.fielddata.IndexParentChildFieldData;
import org.elasticsearch.index.mapper.Uid;
import org.elasticsearch.index.mapper.internal.UidFieldMapper;
@ -66,14 +67,14 @@ public class TopChildrenQuery extends Query {
private final int factor;
private final int incrementalFactor;
private Query originalChildQuery;
private final Filter nonNestedDocsFilter;
private final FixedBitSetFilter nonNestedDocsFilter;
// This field will hold the rewritten form of originalChildQuery, so that we can reuse it
private Query rewrittenChildQuery;
private IndexReader rewriteIndexReader;
// Note, the query is expected to already be filtered to only child type docs
public TopChildrenQuery(IndexParentChildFieldData parentChildIndexFieldData, Query childQuery, String childType, String parentType, ScoreType scoreType, int factor, int incrementalFactor, Filter nonNestedDocsFilter) {
public TopChildrenQuery(IndexParentChildFieldData parentChildIndexFieldData, Query childQuery, String childType, String parentType, ScoreType scoreType, int factor, int incrementalFactor, FixedBitSetFilter nonNestedDocsFilter) {
this.parentChildIndexFieldData = parentChildIndexFieldData;
this.originalChildQuery = childQuery;
this.childType = childType;

View File

@ -29,6 +29,7 @@ import org.elasticsearch.index.aliases.IndexAliasesService;
import org.elasticsearch.index.analysis.AnalysisService;
import org.elasticsearch.index.cache.IndexCache;
import org.elasticsearch.index.engine.IndexEngine;
import org.elasticsearch.index.cache.fixedbitset.FixedBitSetFilterCache;
import org.elasticsearch.index.fielddata.IndexFieldDataService;
import org.elasticsearch.index.gateway.IndexGateway;
import org.elasticsearch.index.mapper.MapperService;
@ -51,6 +52,8 @@ public interface IndexService extends IndexComponent, Iterable<IndexShard> {
IndexFieldDataService fieldData();
FixedBitSetFilterCache fixedBitSetFilterCache();
IndexSettingsService settingsService();
AnalysisService analysisService();

View File

@ -54,6 +54,8 @@ import org.elasticsearch.index.merge.scheduler.MergeSchedulerProvider;
import org.elasticsearch.index.percolator.PercolatorQueriesRegistry;
import org.elasticsearch.index.percolator.PercolatorShardModule;
import org.elasticsearch.index.query.IndexQueryParserService;
import org.elasticsearch.index.cache.fixedbitset.FixedBitSetFilterCache;
import org.elasticsearch.index.cache.fixedbitset.ShardFixedBitSetFilterCacheModule;
import org.elasticsearch.index.search.stats.ShardSearchModule;
import org.elasticsearch.index.settings.IndexSettings;
import org.elasticsearch.index.settings.IndexSettingsService;
@ -115,6 +117,8 @@ public class InternalIndexService extends AbstractIndexComponent implements Inde
private final IndexFieldDataService indexFieldData;
private final FixedBitSetFilterCache fixedBitSetFilterCache;
private final IndexEngine indexEngine;
private final IndexGateway indexGateway;
@ -133,7 +137,8 @@ public class InternalIndexService extends AbstractIndexComponent implements Inde
public InternalIndexService(Injector injector, Index index, @IndexSettings Settings indexSettings, NodeEnvironment nodeEnv, ThreadPool threadPool,
AnalysisService analysisService, MapperService mapperService, IndexQueryParserService queryParserService,
SimilarityService similarityService, IndexAliasesService aliasesService, IndexCache indexCache, IndexEngine indexEngine,
IndexGateway indexGateway, IndexStore indexStore, IndexSettingsService settingsService, IndexFieldDataService indexFieldData) {
IndexGateway indexGateway, IndexStore indexStore, IndexSettingsService settingsService, IndexFieldDataService indexFieldData,
FixedBitSetFilterCache fixedBitSetFilterCache) {
super(index, indexSettings);
this.injector = injector;
this.threadPool = threadPool;
@ -149,6 +154,7 @@ public class InternalIndexService extends AbstractIndexComponent implements Inde
this.indexGateway = indexGateway;
this.indexStore = indexStore;
this.settingsService = settingsService;
this.fixedBitSetFilterCache = fixedBitSetFilterCache;
this.pluginsService = injector.getInstance(PluginsService.class);
this.indicesLifecycle = (InternalIndicesLifecycle) injector.getInstance(IndicesLifecycle.class);
@ -156,6 +162,7 @@ public class InternalIndexService extends AbstractIndexComponent implements Inde
// inject workarounds for cyclic dep
indexCache.filter().setIndexService(this);
indexFieldData.setIndexService(this);
fixedBitSetFilterCache.setIndexService(this);
}
@Override
@ -222,6 +229,11 @@ public class InternalIndexService extends AbstractIndexComponent implements Inde
return indexFieldData;
}
@Override
public FixedBitSetFilterCache fixedBitSetFilterCache() {
return fixedBitSetFilterCache;
}
@Override
public AnalysisService analysisService() {
return this.analysisService;
@ -331,6 +343,7 @@ public class InternalIndexService extends AbstractIndexComponent implements Inde
modules.add(new MergeSchedulerModule(indexSettings));
modules.add(new ShardFilterCacheModule());
modules.add(new ShardQueryCacheModule());
modules.add(new ShardFixedBitSetFilterCacheModule());
modules.add(new ShardFieldDataModule());
modules.add(new TranslogModule(indexSettings));
modules.add(new EngineModule(indexSettings));

View File

@ -46,6 +46,7 @@ import org.elasticsearch.index.mapper.SourceToParse;
import org.elasticsearch.index.merge.MergeStats;
import org.elasticsearch.index.percolator.PercolatorQueriesRegistry;
import org.elasticsearch.index.percolator.stats.ShardPercolateService;
import org.elasticsearch.index.cache.fixedbitset.ShardFixedBitSetFilterCache;
import org.elasticsearch.index.refresh.RefreshStats;
import org.elasticsearch.index.search.stats.SearchStats;
import org.elasticsearch.index.search.stats.ShardSearchService;
@ -129,6 +130,8 @@ public interface IndexShard extends IndexShardComponent {
ShardSuggestService shardSuggestService();
ShardFixedBitSetFilterCache shardFixedBitSetFilterCache();
MapperService mapperService();
IndexFieldDataService indexFieldDataService();

View File

@ -29,7 +29,6 @@ import org.apache.lucene.util.ThreadInterruptedException;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.ElasticsearchIllegalArgumentException;
import org.elasticsearch.ElasticsearchIllegalStateException;
import org.elasticsearch.ExceptionsHelper;
import org.elasticsearch.cluster.routing.ShardRouting;
import org.elasticsearch.cluster.routing.ShardRoutingState;
import org.elasticsearch.common.Booleans;
@ -69,6 +68,7 @@ import org.elasticsearch.index.merge.scheduler.MergeSchedulerProvider;
import org.elasticsearch.index.percolator.PercolatorQueriesRegistry;
import org.elasticsearch.index.percolator.stats.ShardPercolateService;
import org.elasticsearch.index.query.IndexQueryParserService;
import org.elasticsearch.index.cache.fixedbitset.ShardFixedBitSetFilterCache;
import org.elasticsearch.index.refresh.RefreshStats;
import org.elasticsearch.index.search.nested.NonNestedDocsFilter;
import org.elasticsearch.index.search.stats.SearchStats;
@ -131,6 +131,7 @@ public class InternalIndexShard extends AbstractIndexShardComponent implements I
private final IndexFieldDataService indexFieldDataService;
private final IndexService indexService;
private final ShardSuggestService shardSuggestService;
private final ShardFixedBitSetFilterCache shardFixedBitSetFilterCache;
private final Object mutex = new Object();
private final String checkIndexOnStartup;
@ -155,7 +156,7 @@ public class InternalIndexShard extends AbstractIndexShardComponent implements I
public InternalIndexShard(ShardId shardId, @IndexSettings Settings indexSettings, IndexSettingsService indexSettingsService, IndicesLifecycle indicesLifecycle, Store store, Engine engine, MergeSchedulerProvider mergeScheduler, Translog translog,
ThreadPool threadPool, MapperService mapperService, IndexQueryParserService queryParserService, IndexCache indexCache, IndexAliasesService indexAliasesService, ShardIndexingService indexingService, ShardGetService getService, ShardSearchService searchService, ShardIndexWarmerService shardWarmerService,
ShardFilterCache shardFilterCache, ShardFieldData shardFieldData, PercolatorQueriesRegistry percolatorQueriesRegistry, ShardPercolateService shardPercolateService, CodecService codecService,
ShardTermVectorService termVectorService, IndexFieldDataService indexFieldDataService, IndexService indexService, ShardSuggestService shardSuggestService, ShardQueryCache shardQueryCache) {
ShardTermVectorService termVectorService, IndexFieldDataService indexFieldDataService, IndexService indexService, ShardSuggestService shardSuggestService, ShardQueryCache shardQueryCache, ShardFixedBitSetFilterCache shardFixedBitSetFilterCache) {
super(shardId, indexSettings);
this.indicesLifecycle = (InternalIndicesLifecycle) indicesLifecycle;
this.indexSettingsService = indexSettingsService;
@ -182,6 +183,7 @@ public class InternalIndexShard extends AbstractIndexShardComponent implements I
this.indexService = indexService;
this.codecService = codecService;
this.shardSuggestService = shardSuggestService;
this.shardFixedBitSetFilterCache = shardFixedBitSetFilterCache;
state = IndexShardState.CREATED;
this.refreshInterval = indexSettings.getAsTime(INDEX_REFRESH_INTERVAL, engine.defaultRefreshInterval());
@ -229,6 +231,11 @@ public class InternalIndexShard extends AbstractIndexShardComponent implements I
return shardSuggestService;
}
@Override
public ShardFixedBitSetFilterCache shardFixedBitSetFilterCache() {
return shardFixedBitSetFilterCache;
}
@Override
public IndexFieldDataService indexFieldDataService() {
return indexFieldDataService;
@ -544,7 +551,9 @@ public class InternalIndexShard extends AbstractIndexShardComponent implements I
@Override
public SegmentsStats segmentStats() {
return engine.segmentsStats();
SegmentsStats segmentsStats = engine.segmentsStats();
segmentsStats.addFixedBitSetMemoryInBytes(shardFixedBitSetFilterCache.getMemorySizeInBytes());
return segmentsStats;
}
@Override

View File

@ -34,6 +34,7 @@ import org.elasticsearch.index.analysis.AnalysisService;
import org.elasticsearch.index.cache.docset.DocSetCache;
import org.elasticsearch.index.cache.filter.FilterCache;
import org.elasticsearch.index.engine.Engine;
import org.elasticsearch.index.cache.fixedbitset.FixedBitSetFilterCache;
import org.elasticsearch.index.fielddata.IndexFieldDataService;
import org.elasticsearch.index.fieldvisitor.JustSourceFieldsVisitor;
import org.elasticsearch.index.mapper.FieldMapper;
@ -449,6 +450,11 @@ public class PercolateContext extends SearchContext {
return indexService.cache().filter();
}
@Override
public FixedBitSetFilterCache fixedBitSetFilterCache() {
return indexService.fixedBitSetFilterCache();
}
@Override
public DocSetCache docSetCache() {
return indexService.cache().docSet();

View File

@ -261,6 +261,9 @@ public class RestIndicesAction extends AbstractCatAction {
table.addCell("segments.version_map_memory", "sibling:pri;alias:svmm,segmentsVersionMapMemory;default:false;text-align:right;desc:memory used by version map");
table.addCell("pri.segments.version_map_memory", "default:false;text-align:right;desc:memory used by version map");
table.addCell("segments.fixed_bitset_memory", "sibling:pri;alias:sfbm,fixedBitsetMemory;default:false;text-align:right;desc:memory used by fixed bit sets for nested object field types and type filters for types referred in _parent fields");
table.addCell("pri.segments.fixed_bitset_memory", "default:false;text-align:right;desc:memory used by fixed bit sets for nested object field types and type filters for types referred in _parent fields");
table.addCell("warmer.current", "sibling:pri;alias:wc,warmerCurrent;default:false;text-align:right;desc:current warmer ops");
table.addCell("pri.warmer.current", "default:false;text-align:right;desc:current warmer ops");
@ -455,6 +458,9 @@ public class RestIndicesAction extends AbstractCatAction {
table.addCell(indexStats == null ? null : indexStats.getTotal().getSegments().getVersionMapMemory());
table.addCell(indexStats == null ? null : indexStats.getPrimaries().getSegments().getVersionMapMemory());
table.addCell(indexStats == null ? null : indexStats.getTotal().getSegments().getFixedBitSetMemory());
table.addCell(indexStats == null ? null : indexStats.getPrimaries().getSegments().getFixedBitSetMemory());
table.addCell(indexStats == null ? null : indexStats.getTotal().getWarmer().current());
table.addCell(indexStats == null ? null : indexStats.getPrimaries().getWarmer().current());

View File

@ -177,6 +177,7 @@ public class RestNodesAction extends AbstractCatAction {
table.addCell("segments.index_writer_memory", "alias:siwm,segmentsIndexWriterMemory;default:false;text-align:right;desc:memory used by index writer");
table.addCell("segments.index_writer_max_memory", "alias:siwmx,segmentsIndexWriterMaxMemory;default:false;text-align:right;desc:maximum memory index writer may use before it must write buffered documents to a new segment");
table.addCell("segments.version_map_memory", "alias:svmm,segmentsVersionMapMemory;default:false;text-align:right;desc:memory used by version map");
table.addCell("segments.fixed_bitset_memory", "alias:sfbm,fixedBitsetMemory;default:false;text-align:right;desc:memory used by fixed bit sets for nested object field types and type filters for types referred in _parent fields");
table.addCell("suggest.current", "alias:suc,suggestCurrent;default:false;text-align:right;desc:number of current suggest ops");
table.addCell("suggest.time", "alias:suti,suggestTime;default:false;text-align:right;desc:time spend in suggest");
@ -287,6 +288,7 @@ public class RestNodesAction extends AbstractCatAction {
table.addCell(stats == null ? null : stats.getIndices().getSegments().getIndexWriterMemory());
table.addCell(stats == null ? null : stats.getIndices().getSegments().getIndexWriterMaxMemory());
table.addCell(stats == null ? null : stats.getIndices().getSegments().getVersionMapMemory());
table.addCell(stats == null ? null : stats.getIndices().getSegments().getFixedBitSetMemory());
table.addCell(stats == null ? null : stats.getIndices().getSuggest().getCurrent());
table.addCell(stats == null ? null : stats.getIndices().getSuggest().getTime());

View File

@ -148,6 +148,7 @@ public class RestShardsAction extends AbstractCatAction {
table.addCell("segments.index_writer_memory", "alias:siwm,segmentsIndexWriterMemory;default:false;text-align:right;desc:memory used by index writer");
table.addCell("segments.index_writer_max_memory", "alias:siwmx,segmentsIndexWriterMaxMemory;default:false;text-align:right;desc:maximum memory index writer may use before it must write buffered documents to a new segment");
table.addCell("segments.version_map_memory", "alias:svmm,segmentsVersionMapMemory;default:false;text-align:right;desc:memory used by version map");
table.addCell("segments.fixed_bitset_memory", "alias:sfbm,fixedBitsetMemory;default:false;text-align:right;desc:memory used by fixed bit sets for nested object field types and type filters for types referred in _parent fields");
table.addCell("warmer.current", "alias:wc,warmerCurrent;default:false;text-align:right;desc:current warmer ops");
table.addCell("warmer.total", "alias:wto,warmerTotal;default:false;text-align:right;desc:total warmer ops");
@ -248,6 +249,7 @@ public class RestShardsAction extends AbstractCatAction {
table.addCell(shardStats == null ? null : shardStats.getSegments().getIndexWriterMemory());
table.addCell(shardStats == null ? null : shardStats.getSegments().getIndexWriterMaxMemory());
table.addCell(shardStats == null ? null : shardStats.getSegments().getVersionMapMemory());
table.addCell(shardStats == null ? null : shardStats.getSegments().getFixedBitSetMemory());
table.addCell(shardStats == null ? null : shardStats.getWarmer().current());
table.addCell(shardStats == null ? null : shardStats.getWarmer().total());

View File

@ -23,7 +23,6 @@ import org.apache.lucene.index.SortedDocValues;
import org.apache.lucene.search.DocIdSet;
import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.Filter;
import org.apache.lucene.search.join.FixedBitSetCachingWrapperFilter;
import org.apache.lucene.util.Bits;
import org.elasticsearch.ElasticsearchIllegalStateException;
import org.elasticsearch.ExceptionsHelper;
@ -32,6 +31,7 @@ import org.elasticsearch.common.lucene.ReaderContextAware;
import org.elasticsearch.common.lucene.docset.DocIdSets;
import org.elasticsearch.common.util.LongArray;
import org.elasticsearch.common.util.LongObjectPagedHashMap;
import org.elasticsearch.index.cache.fixedbitset.FixedBitSetFilter;
import org.elasticsearch.index.search.child.ConstantScorer;
import org.elasticsearch.search.aggregations.Aggregator;
import org.elasticsearch.search.aggregations.AggregatorFactories;
@ -52,8 +52,8 @@ import java.util.List;
public class ParentToChildrenAggregator extends SingleBucketAggregator implements ReaderContextAware {
private final String parentType;
private final Filter childFilter;
private final Filter parentFilter;
private final FixedBitSetFilter childFilter;
private final FixedBitSetFilter parentFilter;
private final ValuesSource.Bytes.WithOrdinals.ParentChild valuesSource;
// Maybe use PagedGrowableWriter? This will be less wasteful than LongArray, but then we don't have the reuse feature of BigArrays.
@ -75,9 +75,8 @@ public class ParentToChildrenAggregator extends SingleBucketAggregator implement
ValuesSource.Bytes.WithOrdinals.ParentChild valuesSource, long maxOrd) {
super(name, factories, aggregationContext, parent);
this.parentType = parentType;
this.childFilter = childFilter;
// TODO: remove FixedBitSetCachingWrapperFilter once #7031 gets in
this.parentFilter = new FixedBitSetCachingWrapperFilter(parentFilter);
this.childFilter = aggregationContext.searchContext().fixedBitSetFilterCache().getFixedBitSetFilter(childFilter);
this.parentFilter = aggregationContext.searchContext().fixedBitSetFilterCache().getFixedBitSetFilter(parentFilter);
this.parentOrdToBuckets = aggregationContext.bigArrays().newLongArray(maxOrd, false);
this.parentOrdToBuckets.fill(0, maxOrd, -1);
this.parentOrdToOtherBuckets = new LongObjectPagedHashMap<>(aggregationContext.bigArrays());

View File

@ -21,11 +21,11 @@ package org.elasticsearch.search.aggregations.bucket.nested;
import org.apache.lucene.index.AtomicReaderContext;
import org.apache.lucene.search.DocIdSet;
import org.apache.lucene.search.Filter;
import org.apache.lucene.search.join.FixedBitSetCachingWrapperFilter;
import org.apache.lucene.util.Bits;
import org.apache.lucene.util.FixedBitSet;
import org.elasticsearch.common.lucene.ReaderContextAware;
import org.elasticsearch.common.lucene.docset.DocIdSets;
import org.elasticsearch.index.cache.fixedbitset.FixedBitSetFilter;
import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.mapper.object.ObjectMapper;
import org.elasticsearch.index.search.nested.NonNestedDocsFilter;
@ -43,8 +43,8 @@ public class NestedAggregator extends SingleBucketAggregator implements ReaderCo
private final String nestedPath;
private final Aggregator parentAggregator;
private Filter parentFilter;
private final Filter childFilter;
private FixedBitSetFilter parentFilter;
private final FixedBitSetFilter childFilter;
private Bits childDocs;
private FixedBitSet parentDocs;
@ -65,7 +65,7 @@ public class NestedAggregator extends SingleBucketAggregator implements ReaderCo
throw new AggregationExecutionException("[nested] nested path [" + nestedPath + "] is not nested");
}
childFilter = aggregationContext.searchContext().filterCache().cache(objectMapper.nestedTypeFilter());
childFilter = aggregationContext.searchContext().fixedBitSetFilterCache().getFixedBitSetFilter(objectMapper.nestedTypeFilter());
}
@Override
@ -79,9 +79,7 @@ public class NestedAggregator extends SingleBucketAggregator implements ReaderCo
if (parentFilterNotCached == null) {
parentFilterNotCached = NonNestedDocsFilter.INSTANCE;
}
parentFilter = SearchContext.current().filterCache().cache(parentFilterNotCached);
// if the filter cache is disabled, we still need to produce bit sets
parentFilter = new FixedBitSetCachingWrapperFilter(parentFilter);
parentFilter = SearchContext.current().fixedBitSetFilterCache().getFixedBitSetFilter(parentFilterNotCached);
}
try {

View File

@ -25,6 +25,7 @@ import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.Filter;
import org.elasticsearch.common.lucene.ReaderContextAware;
import org.elasticsearch.common.lucene.docset.DocIdSets;
import org.elasticsearch.index.cache.fixedbitset.FixedBitSetFilter;
import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.mapper.object.ObjectMapper;
import org.elasticsearch.index.search.nested.NonNestedDocsFilter;
@ -41,7 +42,7 @@ import java.io.IOException;
*/
public class ReverseNestedAggregator extends SingleBucketAggregator implements ReaderContextAware {
private final Filter parentFilter;
private final FixedBitSetFilter parentFilter;
private DocIdSetIterator parentDocs;
// TODO: Add LongIntPagedHashMap?
@ -56,7 +57,7 @@ public class ReverseNestedAggregator extends SingleBucketAggregator implements R
throw new SearchParseException(context.searchContext(), "Reverse nested aggregation [" + name + "] can only be used inside a [nested] aggregation");
}
if (nestedPath == null) {
parentFilter = SearchContext.current().filterCache().cache(NonNestedDocsFilter.INSTANCE);
parentFilter = SearchContext.current().fixedBitSetFilterCache().getFixedBitSetFilter(NonNestedDocsFilter.INSTANCE);
} else {
MapperService.SmartNameObjectMapper mapper = SearchContext.current().smartNameObjectMapper(nestedPath);
if (mapper == null) {
@ -69,7 +70,7 @@ public class ReverseNestedAggregator extends SingleBucketAggregator implements R
if (!objectMapper.nested().isNested()) {
throw new AggregationExecutionException("[reverse_nested] nested path [" + nestedPath + "] is not nested");
}
parentFilter = SearchContext.current().filterCache().cache(objectMapper.nestedTypeFilter());
parentFilter = SearchContext.current().fixedBitSetFilterCache().getFixedBitSetFilter(objectMapper.nestedTypeFilter());
}
bucketOrdToLastCollectedParentDoc = new LongIntOpenHashMap(32);
aggregationContext.ensureScoreDocsInOrder();

View File

@ -30,6 +30,7 @@ import org.elasticsearch.common.util.BigArrays;
import org.elasticsearch.index.analysis.AnalysisService;
import org.elasticsearch.index.cache.docset.DocSetCache;
import org.elasticsearch.index.cache.filter.FilterCache;
import org.elasticsearch.index.cache.fixedbitset.FixedBitSetFilterCache;
import org.elasticsearch.index.fielddata.IndexFieldDataService;
import org.elasticsearch.index.mapper.FieldMapper;
import org.elasticsearch.index.mapper.FieldMappers;
@ -330,6 +331,11 @@ public class TopHitsContext extends SearchContext {
return context.filterCache();
}
@Override
public FixedBitSetFilterCache fixedBitSetFilterCache() {
return context.fixedBitSetFilterCache();
}
@Override
public DocSetCache docSetCache() {
return context.docSetCache();

View File

@ -41,6 +41,7 @@ import org.elasticsearch.index.analysis.AnalysisService;
import org.elasticsearch.index.cache.docset.DocSetCache;
import org.elasticsearch.index.cache.filter.FilterCache;
import org.elasticsearch.index.engine.Engine;
import org.elasticsearch.index.cache.fixedbitset.FixedBitSetFilterCache;
import org.elasticsearch.index.fielddata.IndexFieldDataService;
import org.elasticsearch.index.mapper.FieldMapper;
import org.elasticsearch.index.mapper.FieldMappers;
@ -439,6 +440,11 @@ public class DefaultSearchContext extends SearchContext {
return indexService.cache().filter();
}
@Override
public FixedBitSetFilterCache fixedBitSetFilterCache() {
return indexService.fixedBitSetFilterCache();
}
public DocSetCache docSetCache() {
return indexService.cache().docSet();
}

View File

@ -34,6 +34,7 @@ import org.elasticsearch.common.util.BigArrays;
import org.elasticsearch.index.analysis.AnalysisService;
import org.elasticsearch.index.cache.docset.DocSetCache;
import org.elasticsearch.index.cache.filter.FilterCache;
import org.elasticsearch.index.cache.fixedbitset.FixedBitSetFilterCache;
import org.elasticsearch.index.fielddata.IndexFieldDataService;
import org.elasticsearch.index.mapper.FieldMapper;
import org.elasticsearch.index.mapper.FieldMappers;
@ -208,6 +209,8 @@ public abstract class SearchContext implements Releasable {
public abstract FilterCache filterCache();
public abstract FixedBitSetFilterCache fixedBitSetFilterCache();
public abstract DocSetCache docSetCache();
public abstract IndexFieldDataService fieldData();

View File

@ -33,6 +33,7 @@ import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.geo.GeoUtils;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.cache.fixedbitset.FixedBitSetFilter;
import org.elasticsearch.index.fielddata.*;
import org.elasticsearch.index.fielddata.IndexFieldData.XFieldComparatorSource.Nested;
import org.elasticsearch.index.mapper.FieldMapper;
@ -155,12 +156,12 @@ public class GeoDistanceSortParser implements SortParser {
}
final Nested nested;
if (objectMapper != null && objectMapper.nested().isNested()) {
Filter rootDocumentsFilter = context.filterCache().cache(NonNestedDocsFilter.INSTANCE);
Filter innerDocumentsFilter;
FixedBitSetFilter rootDocumentsFilter = context.fixedBitSetFilterCache().getFixedBitSetFilter(NonNestedDocsFilter.INSTANCE);
FixedBitSetFilter innerDocumentsFilter;
if (nestedFilter != null) {
innerDocumentsFilter = context.filterCache().cache(nestedFilter);
innerDocumentsFilter = context.fixedBitSetFilterCache().getFixedBitSetFilter(nestedFilter);
} else {
innerDocumentsFilter = context.filterCache().cache(objectMapper.nestedTypeFilter());
innerDocumentsFilter = context.fixedBitSetFilterCache().getFixedBitSetFilter(objectMapper.nestedTypeFilter());
}
nested = new Nested(rootDocumentsFilter, innerDocumentsFilter);
} else {

View File

@ -27,6 +27,7 @@ import org.apache.lucene.search.SortField;
import org.apache.lucene.util.BytesRef;
import org.elasticsearch.ElasticsearchIllegalArgumentException;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.cache.fixedbitset.FixedBitSetFilter;
import org.elasticsearch.index.fielddata.*;
import org.elasticsearch.index.fielddata.IndexFieldData.XFieldComparatorSource.Nested;
import org.elasticsearch.index.fielddata.fieldcomparator.BytesRefFieldComparatorSource;
@ -135,12 +136,12 @@ public class ScriptSortParser implements SortParser {
throw new ElasticsearchIllegalArgumentException("mapping for explicit nested path is not mapped as nested: [" + nestedPath + "]");
}
Filter rootDocumentsFilter = context.filterCache().cache(NonNestedDocsFilter.INSTANCE);
Filter innerDocumentsFilter;
FixedBitSetFilter rootDocumentsFilter = context.fixedBitSetFilterCache().getFixedBitSetFilter(NonNestedDocsFilter.INSTANCE);
FixedBitSetFilter innerDocumentsFilter;
if (nestedFilter != null) {
innerDocumentsFilter = context.filterCache().cache(nestedFilter);
innerDocumentsFilter = context.fixedBitSetFilterCache().getFixedBitSetFilter(nestedFilter);
} else {
innerDocumentsFilter = context.filterCache().cache(objectMapper.nestedTypeFilter());
innerDocumentsFilter = context.fixedBitSetFilterCache().getFixedBitSetFilter(objectMapper.nestedTypeFilter());
}
nested = new Nested(rootDocumentsFilter, innerDocumentsFilter);
} else {

View File

@ -28,6 +28,7 @@ import org.elasticsearch.ElasticsearchIllegalArgumentException;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.cache.fixedbitset.FixedBitSetFilter;
import org.elasticsearch.index.fielddata.IndexFieldData;
import org.elasticsearch.index.fielddata.IndexFieldData.XFieldComparatorSource.Nested;
import org.elasticsearch.index.mapper.FieldMapper;
@ -247,12 +248,12 @@ public class SortParseElement implements SearchParseElement {
}
final Nested nested;
if (objectMapper != null && objectMapper.nested().isNested()) {
Filter rootDocumentsFilter = context.filterCache().cache(NonNestedDocsFilter.INSTANCE);
Filter innerDocumentsFilter;
FixedBitSetFilter rootDocumentsFilter = context.fixedBitSetFilterCache().getFixedBitSetFilter(NonNestedDocsFilter.INSTANCE);
FixedBitSetFilter innerDocumentsFilter;
if (nestedFilter != null) {
innerDocumentsFilter = context.filterCache().cache(nestedFilter);
innerDocumentsFilter = context.fixedBitSetFilterCache().getFixedBitSetFilter(nestedFilter);
} else {
innerDocumentsFilter = context.filterCache().cache(objectMapper.nestedTypeFilter());
innerDocumentsFilter = context.fixedBitSetFilterCache().getFixedBitSetFilter(objectMapper.nestedTypeFilter());
}
nested = new Nested(rootDocumentsFilter, innerDocumentsFilter);
} else {

View File

@ -0,0 +1,99 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch 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.
*/
package org.elasticsearch.index.cache.fixedbitset;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StringField;
import org.apache.lucene.index.*;
import org.apache.lucene.queries.TermFilter;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.RAMDirectory;
import org.elasticsearch.common.lucene.Lucene;
import org.elasticsearch.common.lucene.search.XConstantScoreQuery;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.index.Index;
import org.elasticsearch.test.ElasticsearchTestCase;
import org.junit.Test;
import static org.hamcrest.Matchers.equalTo;
/**
*/
public class FixedBitSetFilterCacheTest extends ElasticsearchTestCase {
@Test
public void testInvalidateEntries() throws Exception {
IndexWriter writer = new IndexWriter(
new RAMDirectory(),
new IndexWriterConfig(Lucene.VERSION, new StandardAnalyzer(Lucene.VERSION)).setMergePolicy(new LogByteSizeMergePolicy())
);
Document document = new Document();
document.add(new StringField("field", "value", Field.Store.NO));
writer.addDocument(document);
writer.commit();
document = new Document();
document.add(new StringField("field", "value", Field.Store.NO));
writer.addDocument(document);
writer.commit();
document = new Document();
document.add(new StringField("field", "value", Field.Store.NO));
writer.addDocument(document);
writer.commit();
IndexReader reader = DirectoryReader.open(writer, false);
IndexSearcher searcher = new IndexSearcher(reader);
FixedBitSetFilterCache cache = new FixedBitSetFilterCache(new Index("test"), ImmutableSettings.EMPTY);
FixedBitSetFilter filter = cache.getFixedBitSetFilter(new TermFilter(new Term("field", "value")));
TopDocs docs = searcher.search(new XConstantScoreQuery(filter), 1);
assertThat(docs.totalHits, equalTo(3));
// now cached
docs = searcher.search(new XConstantScoreQuery(filter), 1);
assertThat(docs.totalHits, equalTo(3));
// There are 3 segments
assertThat(cache.getLoadedFilters().size(), equalTo(3l));
writer.forceMerge(1);
reader.close();
reader = DirectoryReader.open(writer, false);
searcher = new IndexSearcher(reader);
docs = searcher.search(new XConstantScoreQuery(filter), 1);
assertThat(docs.totalHits, equalTo(3));
// now cached
docs = searcher.search(new XConstantScoreQuery(filter), 1);
assertThat(docs.totalHits, equalTo(3));
// Only one segment now, so the size must be 1
assertThat(cache.getLoadedFilters().size(), equalTo(1l));
reader.close();
writer.close();
// There is no reference from readers and writer to any segment in the test index, so the size in the fbs cache must be 0
assertThat(cache.getLoadedFilters().size(), equalTo(0l));
}
}

View File

@ -21,19 +21,26 @@ package org.elasticsearch.index.fielddata;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.index.*;
import org.apache.lucene.search.Filter;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.LuceneTestCase.SuppressCodecs;
import org.elasticsearch.common.lucene.Lucene;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.mapper.*;
import org.elasticsearch.index.mapper.ContentPath;
import org.elasticsearch.index.mapper.FieldMapper;
import org.elasticsearch.index.mapper.Mapper.BuilderContext;
import org.elasticsearch.index.mapper.MapperBuilders;
import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.cache.fixedbitset.FixedBitSetFilterCache;
import org.elasticsearch.index.service.IndexService;
import org.elasticsearch.indices.fielddata.cache.IndicesFieldDataCache;
import org.elasticsearch.test.ElasticsearchSingleNodeTest;
import org.junit.After;
import org.junit.Before;
import static org.elasticsearch.index.fielddata.IndexFieldData.XFieldComparatorSource.Nested;
// we might wanna cut this over to LuceneTestCase
@SuppressCodecs({"Lucene3x", "Lucene40", "Lucene41", "Lucene42", "Lucene45", "Lucene46"})
// avoid codecs that do not support SortedNumerics, SortedSet, etc
@ -115,4 +122,9 @@ public abstract class AbstractFieldDataTests extends ElasticsearchSingleNodeTest
writer.close();
}
protected Nested createNested(Filter parentFilter, Filter childFilter) {
FixedBitSetFilterCache s = indexService.fixedBitSetFilterCache();
return new Nested(s.getFixedBitSetFilter(parentFilter), s.getFixedBitSetFilter(childFilter));
}
}

View File

@ -377,7 +377,7 @@ public abstract class AbstractStringFieldDataTests extends AbstractFieldDataImpl
}
Filter parentFilter = new TermFilter(new Term("type", "parent"));
Filter childFilter = new NotFilter(parentFilter);
Nested nested = new Nested(parentFilter, childFilter);
Nested nested = createNested(parentFilter, childFilter);
BytesRefFieldComparatorSource nestedComparatorSource = new BytesRefFieldComparatorSource(fieldData, missingValue, sortMode, nested);
ToParentBlockJoinQuery query = new ToParentBlockJoinQuery(new XFilteredQuery(new MatchAllDocsQuery(), childFilter), new FixedBitSetCachingWrapperFilter(parentFilter), ScoreMode.None);
Sort sort = new Sort(new SortField("text", nestedComparatorSource));

View File

@ -19,14 +19,12 @@
package org.elasticsearch.index.search.child;
import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.*;
import org.apache.lucene.util.FixedBitSet;
import org.apache.lucene.util.LuceneTestCase;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import org.elasticsearch.common.compress.CompressedString;
import org.elasticsearch.index.cache.fixedbitset.FixedBitSetFilter;
import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.mapper.internal.UidFieldMapper;
import org.elasticsearch.index.service.IndexService;
@ -90,4 +88,9 @@ public abstract class AbstractChildTests extends ElasticsearchSingleNodeLuceneTe
assertThat("actualHit.score != expectedHit.score", actualHit.score, equalTo(expectedHit.score));
}
}
static FixedBitSetFilter wrap(Filter filter) {
return SearchContext.current().fixedBitSetFilterCache().getFixedBitSetFilter(filter);
}
}

View File

@ -35,6 +35,7 @@ import org.elasticsearch.common.lucene.search.NotFilter;
import org.elasticsearch.common.lucene.search.XConstantScoreQuery;
import org.elasticsearch.common.lucene.search.XFilteredQuery;
import org.elasticsearch.index.engine.Engine;
import org.elasticsearch.index.cache.fixedbitset.FixedBitSetFilter;
import org.elasticsearch.index.fielddata.plain.ParentChildIndexFieldData;
import org.elasticsearch.index.mapper.Uid;
import org.elasticsearch.index.mapper.internal.ParentFieldMapper;
@ -75,8 +76,8 @@ public class ChildrenConstantScoreQueryTests extends AbstractChildTests {
Query childQuery = new TermQuery(new Term("field", "value"));
ParentFieldMapper parentFieldMapper = SearchContext.current().mapperService().documentMapper("child").parentFieldMapper();
ParentChildIndexFieldData parentChildIndexFieldData = SearchContext.current().fieldData().getForField(parentFieldMapper);
Filter parentFilter = new TermFilter(new Term(TypeFieldMapper.NAME, "parent"));
Query query = new ChildrenConstantScoreQuery(parentChildIndexFieldData, childQuery, "parent", "child", parentFilter, 12, NonNestedDocsFilter.INSTANCE);
FixedBitSetFilter parentFilter = wrap(new TermFilter(new Term(TypeFieldMapper.NAME, "parent")));
Query query = new ChildrenConstantScoreQuery(parentChildIndexFieldData, childQuery, "parent", "child", parentFilter, 12, wrap(NonNestedDocsFilter.INSTANCE));
QueryUtils.check(query);
}
@ -108,7 +109,7 @@ public class ChildrenConstantScoreQueryTests extends AbstractChildTests {
));
TermQuery childQuery = new TermQuery(new Term("field1", "value" + (1 + random().nextInt(3))));
TermFilter parentFilter = new TermFilter(new Term(TypeFieldMapper.NAME, "parent"));
FixedBitSetFilter parentFilter = wrap(new TermFilter(new Term(TypeFieldMapper.NAME, "parent")));
int shortCircuitParentDocSet = random().nextInt(5);
ParentFieldMapper parentFieldMapper = SearchContext.current().mapperService().documentMapper("child").parentFieldMapper();
ParentChildIndexFieldData parentChildIndexFieldData = SearchContext.current().fieldData().getForField(parentFieldMapper);
@ -203,19 +204,10 @@ public class ChildrenConstantScoreQueryTests extends AbstractChildTests {
ParentFieldMapper parentFieldMapper = SearchContext.current().mapperService().documentMapper("child").parentFieldMapper();
ParentChildIndexFieldData parentChildIndexFieldData = SearchContext.current().fieldData().getForField(parentFieldMapper);
Filter rawParentFilter = new TermFilter(new Term(TypeFieldMapper.NAME, "parent"));
FixedBitSetFilter parentFilter = wrap(new TermFilter(new Term(TypeFieldMapper.NAME, "parent")));
Filter rawFilterMe = new NotFilter(new TermFilter(new Term("filter", "me")));
int max = numUniqueChildValues / 4;
for (int i = 0; i < max; i++) {
// Randomly pick a cached version: there is specific logic inside ChildrenQuery that deals with the fact
// that deletes are applied at the top level when filters are cached.
Filter parentFilter;
if (random().nextBoolean()) {
parentFilter = SearchContext.current().filterCache().cache(rawParentFilter);
} else {
parentFilter = rawParentFilter;
}
// Using this in FQ, will invoke / test the Scorer#advance(..) and also let the Weight#scorer not get live docs as acceptedDocs
Filter filterMe;
if (random().nextBoolean()) {
@ -255,7 +247,7 @@ public class ChildrenConstantScoreQueryTests extends AbstractChildTests {
String childValue = childValues[random().nextInt(numUniqueChildValues)];
TermQuery childQuery = new TermQuery(new Term("field1", childValue));
int shortCircuitParentDocSet = random().nextInt(numParentDocs);
Filter nonNestedDocsFilter = random().nextBoolean() ? NonNestedDocsFilter.INSTANCE : null;
FixedBitSetFilter nonNestedDocsFilter = random().nextBoolean() ? wrap(NonNestedDocsFilter.INSTANCE) : null;
Query query;
if (random().nextBoolean()) {
// Usage in HasChildQueryParser

View File

@ -36,6 +36,7 @@ import org.elasticsearch.common.lease.Releasables;
import org.elasticsearch.common.lucene.search.NotFilter;
import org.elasticsearch.common.lucene.search.XFilteredQuery;
import org.elasticsearch.index.engine.Engine;
import org.elasticsearch.index.cache.fixedbitset.FixedBitSetFilter;
import org.elasticsearch.index.fielddata.plain.ParentChildIndexFieldData;
import org.elasticsearch.index.mapper.Uid;
import org.elasticsearch.index.mapper.internal.ParentFieldMapper;
@ -76,11 +77,11 @@ public class ChildrenQueryTests extends AbstractChildTests {
ScoreType scoreType = ScoreType.values()[random().nextInt(ScoreType.values().length)];
ParentFieldMapper parentFieldMapper = SearchContext.current().mapperService().documentMapper("child").parentFieldMapper();
ParentChildIndexFieldData parentChildIndexFieldData = SearchContext.current().fieldData().getForField(parentFieldMapper);
Filter parentFilter = new TermFilter(new Term(TypeFieldMapper.NAME, "parent"));
FixedBitSetFilter parentFilter = wrap(new TermFilter(new Term(TypeFieldMapper.NAME, "parent")));
int minChildren = random().nextInt(10);
int maxChildren = scaledRandomIntBetween(minChildren, 10);
Query query = new ChildrenQuery(parentChildIndexFieldData, "parent", "child", parentFilter, childQuery, scoreType, minChildren,
maxChildren, 12, NonNestedDocsFilter.INSTANCE);
maxChildren, 12, wrap(NonNestedDocsFilter.INSTANCE));
QueryUtils.check(query);
}
@ -167,19 +168,10 @@ public class ChildrenQueryTests extends AbstractChildTests {
ParentFieldMapper parentFieldMapper = SearchContext.current().mapperService().documentMapper("child").parentFieldMapper();
ParentChildIndexFieldData parentChildIndexFieldData = SearchContext.current().fieldData().getForField(parentFieldMapper);
Filter rawParentFilter = new TermFilter(new Term(TypeFieldMapper.NAME, "parent"));
FixedBitSetFilter parentFilter = wrap(new TermFilter(new Term(TypeFieldMapper.NAME, "parent")));
Filter rawFilterMe = new NotFilter(new TermFilter(new Term("filter", "me")));
int max = numUniqueChildValues / 4;
for (int i = 0; i < max; i++) {
// Randomly pick a cached version: there is specific logic inside ChildrenQuery that deals with the fact
// that deletes are applied at the top level when filters are cached.
Filter parentFilter;
if (random().nextBoolean()) {
parentFilter = SearchContext.current().filterCache().cache(rawParentFilter);
} else {
parentFilter = rawParentFilter;
}
// Using this in FQ, will invoke / test the Scorer#advance(..) and also let the Weight#scorer not get live docs as acceptedDocs
Filter filterMe;
if (random().nextBoolean()) {
@ -220,7 +212,7 @@ public class ChildrenQueryTests extends AbstractChildTests {
Query childQuery = new ConstantScoreQuery(new TermQuery(new Term("field1", childValue)));
int shortCircuitParentDocSet = random().nextInt(numParentDocs);
ScoreType scoreType = ScoreType.values()[random().nextInt(ScoreType.values().length)];
Filter nonNestedDocsFilter = random().nextBoolean() ? NonNestedDocsFilter.INSTANCE : null;
FixedBitSetFilter nonNestedDocsFilter = random().nextBoolean() ? wrap(NonNestedDocsFilter.INSTANCE) : null;
// leave min/max set to 0 half the time
int minChildren = random().nextInt(2) * scaledRandomIntBetween(0, 110);

View File

@ -35,6 +35,7 @@ import org.elasticsearch.common.lucene.search.NotFilter;
import org.elasticsearch.common.lucene.search.XConstantScoreQuery;
import org.elasticsearch.common.lucene.search.XFilteredQuery;
import org.elasticsearch.index.engine.Engine;
import org.elasticsearch.index.cache.fixedbitset.FixedBitSetFilter;
import org.elasticsearch.index.fielddata.plain.ParentChildIndexFieldData;
import org.elasticsearch.index.mapper.Uid;
import org.elasticsearch.index.mapper.internal.ParentFieldMapper;
@ -74,7 +75,7 @@ public class ParentConstantScoreQueryTests extends AbstractChildTests {
Query parentQuery = new TermQuery(new Term("field", "value"));
ParentFieldMapper parentFieldMapper = SearchContext.current().mapperService().documentMapper("child").parentFieldMapper();
ParentChildIndexFieldData parentChildIndexFieldData = SearchContext.current().fieldData().getForField(parentFieldMapper);
Filter childrenFilter = new TermFilter(new Term(TypeFieldMapper.NAME, "child"));
FixedBitSetFilter childrenFilter = wrap(new TermFilter(new Term(TypeFieldMapper.NAME, "child")));
Query query = new ParentConstantScoreQuery(parentChildIndexFieldData, parentQuery, "parent", childrenFilter);
QueryUtils.check(query);
}
@ -161,19 +162,10 @@ public class ParentConstantScoreQueryTests extends AbstractChildTests {
ParentFieldMapper parentFieldMapper = SearchContext.current().mapperService().documentMapper("child").parentFieldMapper();
ParentChildIndexFieldData parentChildIndexFieldData = SearchContext.current().fieldData().getForField(parentFieldMapper);
TermFilter rawChildrenFilter = new TermFilter(new Term(TypeFieldMapper.NAME, "child"));
FixedBitSetFilter childrenFilter = wrap(new TermFilter(new Term(TypeFieldMapper.NAME, "child")));
Filter rawFilterMe = new NotFilter(new TermFilter(new Term("filter", "me")));
int max = numUniqueParentValues / 4;
for (int i = 0; i < max; i++) {
// Randomly pick a cached version: there is specific logic inside ChildrenQuery that deals with the fact
// that deletes are applied at the top level when filters are cached.
Filter childrenFilter;
if (random().nextBoolean()) {
childrenFilter = SearchContext.current().filterCache().cache(rawChildrenFilter);
} else {
childrenFilter = rawChildrenFilter;
}
// Using this in FQ, will invoke / test the Scorer#advance(..) and also let the Weight#scorer not get live docs as acceptedDocs
Filter filterMe;
if (random().nextBoolean()) {

View File

@ -35,6 +35,7 @@ import org.elasticsearch.common.lease.Releasables;
import org.elasticsearch.common.lucene.search.NotFilter;
import org.elasticsearch.common.lucene.search.XFilteredQuery;
import org.elasticsearch.index.engine.Engine;
import org.elasticsearch.index.cache.fixedbitset.FixedBitSetFilter;
import org.elasticsearch.index.fielddata.plain.ParentChildIndexFieldData;
import org.elasticsearch.index.mapper.Uid;
import org.elasticsearch.index.mapper.internal.ParentFieldMapper;
@ -73,7 +74,7 @@ public class ParentQueryTests extends AbstractChildTests {
Query parentQuery = new TermQuery(new Term("field", "value"));
ParentFieldMapper parentFieldMapper = SearchContext.current().mapperService().documentMapper("child").parentFieldMapper();
ParentChildIndexFieldData parentChildIndexFieldData = SearchContext.current().fieldData().getForField(parentFieldMapper);
Filter childrenFilter = new TermFilter(new Term(TypeFieldMapper.NAME, "child"));
FixedBitSetFilter childrenFilter = wrap(new TermFilter(new Term(TypeFieldMapper.NAME, "child")));
Query query = new ParentQuery(parentChildIndexFieldData, parentQuery, "parent", childrenFilter);
QueryUtils.check(query);
}
@ -160,19 +161,10 @@ public class ParentQueryTests extends AbstractChildTests {
ParentFieldMapper parentFieldMapper = SearchContext.current().mapperService().documentMapper("child").parentFieldMapper();
ParentChildIndexFieldData parentChildIndexFieldData = SearchContext.current().fieldData().getForField(parentFieldMapper);
TermFilter rawChildrenFilter = new TermFilter(new Term(TypeFieldMapper.NAME, "child"));
FixedBitSetFilter childrenFilter = wrap(new TermFilter(new Term(TypeFieldMapper.NAME, "child")));
Filter rawFilterMe = new NotFilter(new TermFilter(new Term("filter", "me")));
int max = numUniqueParentValues / 4;
for (int i = 0; i < max; i++) {
// Randomly pick a cached version: there is specific logic inside ChildrenQuery that deals with the fact
// that deletes are applied at the top level when filters are cached.
Filter childrenFilter;
if (random().nextBoolean()) {
childrenFilter = SearchContext.current().filterCache().cache(rawChildrenFilter);
} else {
childrenFilter = rawChildrenFilter;
}
// Using this in FQ, will invoke / test the Scorer#advance(..) and also let the Weight#scorer not get live docs as acceptedDocs
Filter filterMe;
if (random().nextBoolean()) {

View File

@ -57,7 +57,7 @@ public class TopChildrenQueryTests extends AbstractChildTests {
ScoreType scoreType = ScoreType.values()[random().nextInt(ScoreType.values().length)];
ParentFieldMapper parentFieldMapper = SearchContext.current().mapperService().documentMapper("child").parentFieldMapper();
ParentChildIndexFieldData parentChildIndexFieldData = SearchContext.current().fieldData().getForField(parentFieldMapper);
Query query = new TopChildrenQuery(parentChildIndexFieldData, childQuery, "child", "parent", scoreType, 1, 1, NonNestedDocsFilter.INSTANCE);
Query query = new TopChildrenQuery(parentChildIndexFieldData, childQuery, "child", "parent", scoreType, 1, 1, wrap(NonNestedDocsFilter.INSTANCE));
QueryUtils.check(query);
}

View File

@ -210,7 +210,7 @@ public abstract class AbstractNumberNestedSortingTests extends AbstractFieldData
IndexSearcher searcher = new IndexSearcher(DirectoryReader.open(writer, false));
Filter parentFilter = new TermFilter(new Term("__type", "parent"));
Filter childFilter = new NotFilter(parentFilter);
XFieldComparatorSource nestedComparatorSource = createFieldComparator("field2", sortMode, null, new Nested(parentFilter, childFilter));
XFieldComparatorSource nestedComparatorSource = createFieldComparator("field2", sortMode, null, createNested(parentFilter, childFilter));
ToParentBlockJoinQuery query = new ToParentBlockJoinQuery(new XFilteredQuery(new MatchAllDocsQuery(), childFilter), new FixedBitSetCachingWrapperFilter(parentFilter), ScoreMode.None);
Sort sort = new Sort(new SortField("field2", nestedComparatorSource));
@ -244,7 +244,7 @@ public abstract class AbstractNumberNestedSortingTests extends AbstractFieldData
assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[4]).fields[0]).intValue(), equalTo(9));
childFilter = new TermFilter(new Term("filter_1", "T"));
nestedComparatorSource = createFieldComparator("field2", sortMode, null, new Nested(parentFilter, childFilter));
nestedComparatorSource = createFieldComparator("field2", sortMode, null, createNested(parentFilter, childFilter));
query = new ToParentBlockJoinQuery(
new XFilteredQuery(new MatchAllDocsQuery(), childFilter),
new FixedBitSetCachingWrapperFilter(parentFilter),
@ -280,7 +280,7 @@ public abstract class AbstractNumberNestedSortingTests extends AbstractFieldData
assertThat(topDocs.scoreDocs[4].doc, equalTo(3));
assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[4]).fields[0]).intValue(), equalTo(9));
nestedComparatorSource = createFieldComparator("field2", sortMode, 127, new Nested(parentFilter, childFilter));
nestedComparatorSource = createFieldComparator("field2", sortMode, 127, createNested(parentFilter, childFilter));
sort = new Sort(new SortField("field2", nestedComparatorSource, true));
topDocs = searcher.search(new TermQuery(new Term("__type", "parent")), 5, sort);
assertThat(topDocs.totalHits, equalTo(8));
@ -296,7 +296,7 @@ public abstract class AbstractNumberNestedSortingTests extends AbstractFieldData
assertThat(topDocs.scoreDocs[4].doc, equalTo(7));
assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[4]).fields[0]).intValue(), equalTo(8));
nestedComparatorSource = createFieldComparator("field2", sortMode, -127, new Nested(parentFilter, childFilter));
nestedComparatorSource = createFieldComparator("field2", sortMode, -127, createNested(parentFilter, childFilter));
sort = new Sort(new SortField("field2", nestedComparatorSource));
topDocs = searcher.search(new TermQuery(new Term("__type", "parent")), 5, sort);
assertThat(topDocs.totalHits, equalTo(8));
@ -321,7 +321,7 @@ public abstract class AbstractNumberNestedSortingTests extends AbstractFieldData
protected void assertAvgScoreMode(Filter parentFilter, IndexSearcher searcher) throws IOException {
MultiValueMode sortMode = MultiValueMode.AVG;
Filter childFilter = new NotFilter(parentFilter);
XFieldComparatorSource nestedComparatorSource = createFieldComparator("field2", sortMode, -127, new Nested(parentFilter, childFilter));
XFieldComparatorSource nestedComparatorSource = createFieldComparator("field2", sortMode, -127, createNested(parentFilter, childFilter));
Query query = new ToParentBlockJoinQuery(new XFilteredQuery(new MatchAllDocsQuery(), childFilter), new FixedBitSetCachingWrapperFilter(parentFilter), ScoreMode.None);
Sort sort = new Sort(new SortField("field2", nestedComparatorSource));
TopDocs topDocs = searcher.search(query, 5, sort);

View File

@ -62,7 +62,7 @@ public class DoubleNestedSortingTests extends AbstractNumberNestedSortingTests {
protected void assertAvgScoreMode(Filter parentFilter, IndexSearcher searcher) throws IOException {
MultiValueMode sortMode = MultiValueMode.AVG;
Filter childFilter = new NotFilter(parentFilter);
XFieldComparatorSource nestedComparatorSource = createFieldComparator("field2", sortMode, -127, new Nested(parentFilter, childFilter));
XFieldComparatorSource nestedComparatorSource = createFieldComparator("field2", sortMode, -127, createNested(parentFilter, childFilter));
Query query = new ToParentBlockJoinQuery(new XFilteredQuery(new MatchAllDocsQuery(), childFilter), new FixedBitSetCachingWrapperFilter(parentFilter), ScoreMode.None);
Sort sort = new Sort(new SortField("field2", nestedComparatorSource));
TopDocs topDocs = searcher.search(query, 5, sort);

View File

@ -62,7 +62,7 @@ public class FloatNestedSortingTests extends DoubleNestedSortingTests {
protected void assertAvgScoreMode(Filter parentFilter, IndexSearcher searcher, IndexFieldData.XFieldComparatorSource innerFieldComparator) throws IOException {
MultiValueMode sortMode = MultiValueMode.AVG;
Filter childFilter = new NotFilter(parentFilter);
XFieldComparatorSource nestedComparatorSource = createFieldComparator("field2", sortMode, -127, new Nested(parentFilter, childFilter));
XFieldComparatorSource nestedComparatorSource = createFieldComparator("field2", sortMode, -127, createNested(parentFilter, childFilter));
Query query = new ToParentBlockJoinQuery(new XFilteredQuery(new MatchAllDocsQuery(), childFilter), new FixedBitSetCachingWrapperFilter(parentFilter), ScoreMode.None);
Sort sort = new Sort(new SortField("field2", nestedComparatorSource));
TopDocs topDocs = searcher.search(query, 5, sort);

View File

@ -35,9 +35,11 @@ import org.elasticsearch.common.lucene.search.AndFilter;
import org.elasticsearch.common.lucene.search.NotFilter;
import org.elasticsearch.common.lucene.search.XFilteredQuery;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.index.fielddata.*;
import org.elasticsearch.index.fielddata.AbstractFieldDataTests;
import org.elasticsearch.index.fielddata.FieldDataType;
import org.elasticsearch.index.fielddata.IndexFieldData;
import org.elasticsearch.index.fielddata.IndexFieldData.XFieldComparatorSource;
import org.elasticsearch.index.fielddata.IndexFieldData.XFieldComparatorSource.Nested;
import org.elasticsearch.index.fielddata.NoOrdinalsStringFieldDataTests;
import org.elasticsearch.index.fielddata.fieldcomparator.BytesRefFieldComparatorSource;
import org.elasticsearch.index.fielddata.plain.PagedBytesIndexFieldData;
import org.elasticsearch.search.MultiValueMode;
@ -107,7 +109,7 @@ public class NestedSortingTests extends AbstractFieldDataTests {
private TopDocs getTopDocs(IndexSearcher searcher, IndexFieldData<?> indexFieldData, String missingValue, MultiValueMode sortMode, int n, boolean reverse) throws IOException {
Filter parentFilter = new TermFilter(new Term("__type", "parent"));
Filter childFilter = new TermFilter(new Term("__type", "child"));
XFieldComparatorSource nestedComparatorSource = indexFieldData.comparatorSource(missingValue, sortMode, new Nested(parentFilter, childFilter));
XFieldComparatorSource nestedComparatorSource = indexFieldData.comparatorSource(missingValue, sortMode, createNested(parentFilter, childFilter));
Query query = new ConstantScoreQuery(parentFilter);
Sort sort = new Sort(new SortField("f", nestedComparatorSource, reverse));
return searcher.search(query, n, sort);
@ -273,7 +275,7 @@ public class NestedSortingTests extends AbstractFieldDataTests {
PagedBytesIndexFieldData indexFieldData = getForField("field2");
Filter parentFilter = new TermFilter(new Term("__type", "parent"));
Filter childFilter = new NotFilter(parentFilter);
BytesRefFieldComparatorSource nestedComparatorSource = new BytesRefFieldComparatorSource(indexFieldData, null, sortMode, new Nested(parentFilter, childFilter));
BytesRefFieldComparatorSource nestedComparatorSource = new BytesRefFieldComparatorSource(indexFieldData, null, sortMode, createNested(parentFilter, childFilter));
ToParentBlockJoinQuery query = new ToParentBlockJoinQuery(new XFilteredQuery(new MatchAllDocsQuery(), childFilter), new FixedBitSetCachingWrapperFilter(parentFilter), ScoreMode.None);
Sort sort = new Sort(new SortField("field2", nestedComparatorSource));
@ -292,7 +294,7 @@ public class NestedSortingTests extends AbstractFieldDataTests {
assertThat(((BytesRef) ((FieldDoc) topDocs.scoreDocs[4]).fields[0]).utf8ToString(), equalTo("i"));
sortMode = MultiValueMode.MAX;
nestedComparatorSource = new BytesRefFieldComparatorSource(indexFieldData, null, sortMode, new Nested(parentFilter, childFilter));
nestedComparatorSource = new BytesRefFieldComparatorSource(indexFieldData, null, sortMode, createNested(parentFilter, childFilter));
sort = new Sort(new SortField("field2", nestedComparatorSource, true));
topDocs = searcher.search(query, 5, sort);
assertThat(topDocs.totalHits, equalTo(7));
@ -310,7 +312,7 @@ public class NestedSortingTests extends AbstractFieldDataTests {
childFilter = new AndFilter(Arrays.asList(new NotFilter(parentFilter), new TermFilter(new Term("filter_1", "T"))));
nestedComparatorSource = new BytesRefFieldComparatorSource(indexFieldData, null, sortMode, new Nested(parentFilter, childFilter));
nestedComparatorSource = new BytesRefFieldComparatorSource(indexFieldData, null, sortMode, createNested(parentFilter, childFilter));
query = new ToParentBlockJoinQuery(
new XFilteredQuery(new MatchAllDocsQuery(), childFilter),
new FixedBitSetCachingWrapperFilter(parentFilter),

View File

@ -21,6 +21,7 @@ package org.elasticsearch.nested;
import org.apache.lucene.search.Explanation;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthStatus;
import org.elasticsearch.action.admin.cluster.stats.ClusterStatsResponse;
import org.elasticsearch.action.admin.indices.stats.IndicesStatsResponse;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetResponse;
@ -29,6 +30,7 @@ import org.elasticsearch.action.search.SearchPhaseExecutionException;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.query.FilterBuilders;
@ -1161,6 +1163,64 @@ public class SimpleNestedTests extends ElasticsearchIntegrationTest {
assertThat(searchResponse.getHits().getHits()[2].sortValues()[0].toString(), equalTo("3"));
}
@Test
public void testCheckFixedBitSetCache() throws Exception {
boolean loadFixedBitSeLazily = randomBoolean();
ImmutableSettings.Builder settingsBuilder = ImmutableSettings.builder().put(indexSettings())
.put("index.refresh_interval", -1);
if (loadFixedBitSeLazily) {
settingsBuilder.put("index.load_fixed_bitset_filters_eagerly", false);
}
assertAcked(prepareCreate("test")
.setSettings(settingsBuilder)
.addMapping("type")
);
client().prepareIndex("test", "type", "0").setSource("field", "value").get();
client().prepareIndex("test", "type", "1").setSource("field", "value").get();
refresh();
ensureSearchable("test");
// No nested mapping yet, there shouldn't be anything in the fixed bit set cache
ClusterStatsResponse clusterStatsResponse = client().admin().cluster().prepareClusterStats().get();
assertThat(clusterStatsResponse.getIndicesStats().getSegments().getFixedBitSetMemoryInBytes(), equalTo(0l));
// Now add nested mapping
assertAcked(
client().admin().indices().preparePutMapping("test").setType("type").setSource("array1", "type=nested")
);
XContentBuilder builder = jsonBuilder().startObject()
.startArray("array1").startObject().field("field1", "value1").endObject().endArray()
.endObject();
// index simple data
client().prepareIndex("test", "type", "2").setSource(builder).get();
client().prepareIndex("test", "type", "3").setSource(builder).get();
client().prepareIndex("test", "type", "4").setSource(builder).get();
client().prepareIndex("test", "type", "5").setSource(builder).get();
client().prepareIndex("test", "type", "6").setSource(builder).get();
refresh();
ensureSearchable("test");
if (loadFixedBitSeLazily) {
clusterStatsResponse = client().admin().cluster().prepareClusterStats().get();
assertThat(clusterStatsResponse.getIndicesStats().getSegments().getFixedBitSetMemoryInBytes(), equalTo(0l));
// only when querying with nested the fixed bitsets are loaded
SearchResponse searchResponse = client().prepareSearch("test")
.setQuery(nestedQuery("array1", termQuery("field1", "value1")))
.get();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(5l));
}
clusterStatsResponse = client().admin().cluster().prepareClusterStats().get();
assertThat(clusterStatsResponse.getIndicesStats().getSegments().getFixedBitSetMemoryInBytes(), greaterThan(0l));
assertAcked(client().admin().indices().prepareDelete("test"));
clusterStatsResponse = client().admin().cluster().prepareClusterStats().get();
assertThat(clusterStatsResponse.getIndicesStats().getSegments().getFixedBitSetMemoryInBytes(), equalTo(0l));
}
/**
*/
private void assertDocumentCount(String index, long numdocs) {

View File

@ -20,6 +20,7 @@ package org.elasticsearch.search.child;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.ElasticsearchIllegalArgumentException;
import org.elasticsearch.action.admin.cluster.stats.ClusterStatsResponse;
import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheResponse;
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
@ -347,6 +348,63 @@ public class SimpleChildQuerySearchTests extends ElasticsearchIntegrationTest {
assertThat(indicesStatsResponse.getTotal().getFieldData().getMemorySizeInBytes(), equalTo(0l));
}
@Test
public void testCheckFixedBitSetCache() throws Exception {
boolean loadFixedBitSetLazily = randomBoolean();
ImmutableSettings.Builder settingsBuilder = ImmutableSettings.builder().put(indexSettings())
.put("index.refresh_interval", -1);
if (loadFixedBitSetLazily) {
settingsBuilder.put("index.load_fixed_bitset_filters_eagerly", false);
}
// enforce lazy loading to make sure that p/c stats are not counted as part of field data
assertAcked(prepareCreate("test")
.setSettings(settingsBuilder)
.addMapping("parent")
);
client().prepareIndex("test", "parent", "p0").setSource("p_field", "p_value0").get();
client().prepareIndex("test", "parent", "p1").setSource("p_field", "p_value1").get();
refresh();
ensureSearchable("test");
// No _parent field yet, there shouldn't be anything in the parent id cache
ClusterStatsResponse clusterStatsResponse = client().admin().cluster().prepareClusterStats().get();
assertThat(clusterStatsResponse.getIndicesStats().getSegments().getFixedBitSetMemoryInBytes(), equalTo(0l));
// Now add mapping + children
assertAcked(
client().admin().indices().preparePutMapping("test").setType("child").setSource("_parent", "type=parent")
);
// index simple data
client().prepareIndex("test", "child", "c1").setSource("c_field", "red").setParent("p1").get();
client().prepareIndex("test", "child", "c2").setSource("c_field", "yellow").setParent("p1").get();
client().prepareIndex("test", "parent", "p2").setSource("p_field", "p_value2").get();
client().prepareIndex("test", "child", "c3").setSource("c_field", "blue").setParent("p2").get();
client().prepareIndex("test", "child", "c4").setSource("c_field", "red").setParent("p2").get();
refresh();
ensureSearchable("test");
if (loadFixedBitSetLazily) {
clusterStatsResponse = client().admin().cluster().prepareClusterStats().get();
assertThat(clusterStatsResponse.getIndicesStats().getSegments().getFixedBitSetMemoryInBytes(), equalTo(0l));
// only when querying with has_child the fixed bitsets are loaded
SearchResponse searchResponse = client().prepareSearch("test")
// Use setShortCircuitCutoff(0), otherwise the parent filter isn't used.
.setQuery(hasChildQuery("child", termQuery("c_field", "blue")).setShortCircuitCutoff(0))
.get();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
}
clusterStatsResponse = client().admin().cluster().prepareClusterStats().get();
assertThat(clusterStatsResponse.getIndicesStats().getSegments().getFixedBitSetMemoryInBytes(), greaterThan(0l));
assertAcked(client().admin().indices().prepareDelete("test"));
clusterStatsResponse = client().admin().cluster().prepareClusterStats().get();
assertThat(clusterStatsResponse.getIndicesStats().getSegments().getFixedBitSetMemoryInBytes(), equalTo(0l));
}
@Test
// See: https://github.com/elasticsearch/elasticsearch/issues/3290
public void testCachingBug_withFqueryFilter() throws Exception {
@ -719,7 +777,7 @@ public class SimpleChildQuerySearchTests extends ElasticsearchIntegrationTest {
client().prepareIndex("test", "child", "1").setParent("1").setSource("c_field", 1).get();
client().admin().indices().prepareFlush("test").get();
client().prepareIndex("test", "type1", "1").setSource("p_field", "p_value1").get();
client().prepareIndex("test", "type1", "1").setSource("p_field", 1).get();
client().admin().indices().prepareFlush("test").get();
SearchResponse searchResponse = client().prepareSearch("test")

View File

@ -133,6 +133,7 @@ public final class ExternalTestCluster extends TestCluster {
assertThat("Fielddata size must be 0 on node: " + stats.getNode(), stats.getIndices().getFieldData().getMemorySizeInBytes(), equalTo(0l));
assertThat("Filter cache size must be 0 on node: " + stats.getNode(), stats.getIndices().getFilterCache().getMemorySizeInBytes(), equalTo(0l));
assertThat("FixedBitSet cache size must be 0 on node: " + stats.getNode(), stats.getIndices().getSegments().getFixedBitSetMemoryInBytes(), equalTo(0l));
}
}
}

View File

@ -1542,6 +1542,7 @@ public final class InternalTestCluster extends TestCluster {
NodeStats stats = nodeService.stats(CommonStatsFlags.ALL, false, false, false, false, false, false, false, false, false);
assertThat("Fielddata size must be 0 on node: " + stats.getNode(), stats.getIndices().getFieldData().getMemorySizeInBytes(), equalTo(0l));
assertThat("Filter cache size must be 0 on node: " + stats.getNode(), stats.getIndices().getFilterCache().getMemorySizeInBytes(), equalTo(0l));
assertThat("FixedBitSet cache size must be 0 on node: " + stats.getNode(), stats.getIndices().getSegments().getFixedBitSetMemoryInBytes(), equalTo(0l));
}
}
}

View File

@ -29,6 +29,7 @@ import org.elasticsearch.common.util.BigArrays;
import org.elasticsearch.index.analysis.AnalysisService;
import org.elasticsearch.index.cache.docset.DocSetCache;
import org.elasticsearch.index.cache.filter.FilterCache;
import org.elasticsearch.index.cache.fixedbitset.FixedBitSetFilterCache;
import org.elasticsearch.index.fielddata.IndexFieldDataService;
import org.elasticsearch.index.mapper.FieldMapper;
import org.elasticsearch.index.mapper.FieldMappers;
@ -69,6 +70,7 @@ public class TestSearchContext extends SearchContext {
final IndexService indexService;
final FilterCache filterCache;
final IndexFieldDataService indexFieldDataService;
final FixedBitSetFilterCache fixedBitSetFilterCache;
final ThreadPool threadPool;
ContextIndexSearcher searcher;
@ -80,8 +82,9 @@ public class TestSearchContext extends SearchContext {
this.pageCacheRecycler = pageCacheRecycler;
this.bigArrays = bigArrays.withCircuitBreaking();
this.indexService = indexService;
this.filterCache = filterCache;
this.indexFieldDataService = indexFieldDataService;
this.filterCache = indexService.cache().filter();
this.indexFieldDataService = indexService.fieldData();
this.fixedBitSetFilterCache = indexService.fixedBitSetFilterCache();
this.threadPool = threadPool;
}
@ -92,6 +95,7 @@ public class TestSearchContext extends SearchContext {
this.filterCache = null;
this.indexFieldDataService = null;
this.threadPool = null;
this.fixedBitSetFilterCache = null;
}
public void setTypes(String... types) {
@ -321,6 +325,11 @@ public class TestSearchContext extends SearchContext {
return filterCache;
}
@Override
public FixedBitSetFilterCache fixedBitSetFilterCache() {
return fixedBitSetFilterCache;
}
@Override
public DocSetCache docSetCache() {
return null;