From b0e532b7f32c1822e93325ddcf43d772c7ae8073 Mon Sep 17 00:00:00 2001 From: Mikhail Khludnev Date: Sun, 15 Dec 2019 00:34:52 +0300 Subject: [PATCH] SOLR-14051: removing Block Join Facet Component in favor of uniqueBlock(\_root_). --- solr/CHANGES.txt | 6 + .../apache/solr/search/join/BitSetSlice.java | 45 -- .../join/BlockJoinDocSetFacetComponent.java | 195 ------ .../search/join/BlockJoinFacetAccsHolder.java | 83 --- .../search/join/BlockJoinFacetComponent.java | 23 - .../join/BlockJoinFacetComponentSupport.java | 158 ----- .../search/join/BlockJoinFacetFilter.java | 96 --- .../join/BlockJoinFieldFacetAccumulator.java | 235 ------- .../search/join/BlockJoinParentQParser.java | 1 + .../join/ChildFieldValueSourceParser.java | 7 +- .../solr/search/join/ScoreModeParser.java | 1 + .../conf/schema-blockjoinfacetcomponent.xml | 40 -- .../solrconfig-blockjoinfacetcomponent.xml | 58 -- .../solr/search/join/BJQParserTest.java | 6 +- .../join/BlockJoinFacetDistribTest.java | 237 ------- .../search/join/BlockJoinFacetRandomTest.java | 637 ------------------ .../search/join/BlockJoinFacetSimpleTest.java | 121 ---- .../search/join/TestScoreJoinQPNoScore.java | 5 +- .../search/join/TestScoreJoinQPScore.java | 4 +- .../join/another/BJQFilterAccessibleTest.java | 3 +- .../src/blockjoin-faceting.adoc | 115 ---- solr/solr-ref-guide/src/faceting.adoc | 1 - .../src/json-faceting-domain-changes.adoc | 2 +- .../src/searching-nested-documents.adoc | 2 +- 24 files changed, 28 insertions(+), 2053 deletions(-) delete mode 100644 solr/core/src/java/org/apache/solr/search/join/BitSetSlice.java delete mode 100644 solr/core/src/java/org/apache/solr/search/join/BlockJoinDocSetFacetComponent.java delete mode 100644 solr/core/src/java/org/apache/solr/search/join/BlockJoinFacetAccsHolder.java delete mode 100644 solr/core/src/java/org/apache/solr/search/join/BlockJoinFacetComponent.java delete mode 100644 solr/core/src/java/org/apache/solr/search/join/BlockJoinFacetComponentSupport.java delete mode 100644 solr/core/src/java/org/apache/solr/search/join/BlockJoinFacetFilter.java delete mode 100644 solr/core/src/java/org/apache/solr/search/join/BlockJoinFieldFacetAccumulator.java delete mode 100644 solr/core/src/test-files/solr/collection1/conf/schema-blockjoinfacetcomponent.xml delete mode 100644 solr/core/src/test-files/solr/collection1/conf/solrconfig-blockjoinfacetcomponent.xml delete mode 100644 solr/core/src/test/org/apache/solr/search/join/BlockJoinFacetDistribTest.java delete mode 100644 solr/core/src/test/org/apache/solr/search/join/BlockJoinFacetRandomTest.java delete mode 100644 solr/core/src/test/org/apache/solr/search/join/BlockJoinFacetSimpleTest.java delete mode 100644 solr/solr-ref-guide/src/blockjoin-faceting.adoc diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt index 31d926bb491..4d2602625d2 100644 --- a/solr/CHANGES.txt +++ b/solr/CHANGES.txt @@ -75,6 +75,9 @@ Upgrade Notes * SOLR-13817: Legacy SolrCache implementations (LRUCache, LFUCache, FastLRUCache) have been removed. Users have to modify their existing configurations to use CaffeineCache instead. (ab) +* SOLR-14092: Deprecated BlockJoinFacetComponent and BlockJoinDocSetFacetComponent are removed + Users are encouraged to migrate to uniqueBlock() in JSON Facet API. (Mikhail Khludnev) + Improvements ---------------------- @@ -110,6 +113,9 @@ Upgrade Notes * SOLR-14026: Upgrade Jetty to 9.4.24.v20191120 and dropwizard to 4.1.2 (Erick Erickson) +* SOLR-14092: BlockJoinFacetComponent is marked for deprecation and will be removed in 9.0. + Users are encouraged to migrate to uniqueBlock() in JSON Facet API. (Mikhail Khludnev) + New Features --------------------- (No changes) diff --git a/solr/core/src/java/org/apache/solr/search/join/BitSetSlice.java b/solr/core/src/java/org/apache/solr/search/join/BitSetSlice.java deleted file mode 100644 index 824c4e25dcf..00000000000 --- a/solr/core/src/java/org/apache/solr/search/join/BitSetSlice.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.solr.search.join; - -import org.apache.lucene.util.FixedBitSet; - -class BitSetSlice { - private final FixedBitSet fbs; - private final int off; - private final int len; - - BitSetSlice(FixedBitSet fbs, int off, int len) { - this.fbs = fbs; - this.off = off; - this.len = len; - } - - public boolean get(int pos) { - return fbs.get(pos + off); - } - - public int prevSetBit(int pos) { - int result = fbs.prevSetBit(pos + off) - off; - return (result < 0) ? -1 : result; - } - - public int nextSetBit(int pos) { - int result = fbs.nextSetBit(pos + off) - off; - return (result >= len) ? -1 : result; - } -} diff --git a/solr/core/src/java/org/apache/solr/search/join/BlockJoinDocSetFacetComponent.java b/solr/core/src/java/org/apache/solr/search/join/BlockJoinDocSetFacetComponent.java deleted file mode 100644 index b8f303491f2..00000000000 --- a/solr/core/src/java/org/apache/solr/search/join/BlockJoinDocSetFacetComponent.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.solr.search.join; - -import java.io.IOException; -import java.util.List; - -import org.apache.lucene.index.LeafReaderContext; -import org.apache.lucene.search.BooleanClause; -import org.apache.lucene.search.BooleanQuery; -import org.apache.lucene.search.DocIdSet; -import org.apache.lucene.search.DocIdSetIterator; -import org.apache.lucene.search.MatchAllDocsQuery; -import org.apache.lucene.search.Query; -import org.apache.lucene.search.join.ToParentBlockJoinQuery; -import org.apache.solr.common.SolrException; -import org.apache.solr.handler.component.ResponseBuilder; -import org.apache.solr.search.BitDocSet; -import org.apache.solr.search.DocSet; -import org.apache.solr.search.Filter; -import org.apache.solr.search.QueryContext; -import org.apache.solr.search.facet.BlockJoin; -import org.apache.solr.search.join.BlockJoinFieldFacetAccumulator.AggregatableDocIter; - -/** - * Calculates facets on children documents and aggregates hits by parent documents. - * Enables when child.facet.field parameter specifies a field name for faceting. - * So far it supports string fields only. It requires to search by {@link ToParentBlockJoinQuery}. - * */ -public class BlockJoinDocSetFacetComponent extends BlockJoinFacetComponentSupport { - - private final String bjqKey = this.getClass().getSimpleName()+".bjq"; - - private static final class SegmentChildren implements AggregatableDocIter { - - private final BitDocSet allParentsBitsDocSet; - private int nextDoc = DocIdSetIterator.NO_MORE_DOCS; - private DocIdSetIterator disi; - private int currentParent=-1; - final LeafReaderContext segment; - final DocIdSet childrenMatches; - - private SegmentChildren(LeafReaderContext subCtx, DocIdSet dis, BitDocSet allParentsBitsDocSet) { - this.allParentsBitsDocSet = allParentsBitsDocSet; - this.childrenMatches = dis; - this.segment = subCtx; - reset(); - } - - @Override - public Integer next() { - return nextDoc(); - } - - @Override - public boolean hasNext() { - return nextDoc != DocIdSetIterator.NO_MORE_DOCS; - } - - @Override - public float score() { - return 0; - } - - @Override - public int nextDoc() { - int lastDoc = nextDoc; - assert nextDoc != DocIdSetIterator.NO_MORE_DOCS; - if (lastDoc>currentParent) { // we passed the previous block, and need to reevaluate a parent - currentParent = allParentsBitsDocSet.getBits().nextSetBit(lastDoc+segment.docBase)-segment.docBase; - } - try { - nextDoc = disi.nextDoc(); - } catch (IOException e) { - throw new RuntimeException(e); - } - return lastDoc; - } - - @Override - public void reset() { - currentParent=-1; - try { - disi = childrenMatches.iterator(); - if (disi != null) { - nextDoc = disi.nextDoc(); - }else{ - nextDoc = DocIdSetIterator.NO_MORE_DOCS; - } - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - @Override - public int getAggKey() { - return currentParent; - } - } - - public BlockJoinDocSetFacetComponent() {} - - @Override - public void prepare(ResponseBuilder rb) throws IOException { - - if (getChildFacetFields(rb.req) != null) { - validateQuery(rb.getQuery()); - rb.setNeedDocSet(true); - rb.req.getContext().put(bjqKey, extractChildQuery(rb.getQuery())); - } - } - - private ToParentBlockJoinQuery extractChildQuery(Query query) { - if (!(query instanceof ToParentBlockJoinQuery)) { - if (query instanceof BooleanQuery) { - List clauses = ((BooleanQuery) query).clauses(); - ToParentBlockJoinQuery once = null; - for (BooleanClause clause : clauses) { - if (clause.getQuery() instanceof ToParentBlockJoinQuery) { - if (once==null) { - once = (ToParentBlockJoinQuery) clause.getQuery(); - } else { - throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "can't choose between " + - once + " and " + clause.getQuery()); - } - } - } - if (once!=null) { - return once; - } - } - throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, NO_TO_PARENT_BJQ_MESSAGE); - } - else{ - return (ToParentBlockJoinQuery) query; - } - } - - @Override - public void process(ResponseBuilder rb) throws IOException { - final BlockJoinParentQParser.AllParentsAware bjq = - (BlockJoinParentQParser.AllParentsAware) rb.req.getContext().get(bjqKey); - if(bjq!=null){ - final DocSet parentResult = rb.getResults().docSet; - final BitDocSet allParentsBitsDocSet = rb.req.getSearcher().getDocSetBits(bjq.getParentQuery()); - final DocSet allChildren = BlockJoin.toChildren(parentResult, - allParentsBitsDocSet, - rb.req.getSearcher().getDocSetBits( new MatchAllDocsQuery() ), - QueryContext.newContext(rb.req.getSearcher())); - - final DocSet childQueryDocSet = rb.req.getSearcher().getDocSet(bjq.getChildQuery()); - final DocSet selectedChildren = allChildren.intersection(childQueryDocSet); - - // don't include parent into facet counts - //childResult = childResult.union(parentResult);// just to mimic the current logic - - final List leaves = rb.req.getSearcher().getIndexReader().leaves(); - - Filter filter = selectedChildren.getTopFilter(); - - final BlockJoinFacetAccsHolder facetCounter = new BlockJoinFacetAccsHolder(rb.req); - - for (int subIdx = 0; subIdx < leaves.size(); subIdx++) { - LeafReaderContext subCtx = leaves.get(subIdx); - DocIdSet dis = filter.getDocIdSet(subCtx, null); // solr docsets already exclude any deleted docs - - AggregatableDocIter iter = new SegmentChildren(subCtx, dis, allParentsBitsDocSet); - - if (iter.hasNext()){ - facetCounter.doSetNextReader(subCtx); - facetCounter.countFacets(iter); - } - } - facetCounter.finish(); - - rb.req.getContext().put(COLLECTOR_CONTEXT_PARAM,facetCounter); - super.process(rb); - } - - } -} diff --git a/solr/core/src/java/org/apache/solr/search/join/BlockJoinFacetAccsHolder.java b/solr/core/src/java/org/apache/solr/search/join/BlockJoinFacetAccsHolder.java deleted file mode 100644 index 769a9c82300..00000000000 --- a/solr/core/src/java/org/apache/solr/search/join/BlockJoinFacetAccsHolder.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.solr.search.join; - -import java.io.IOException; - -import org.apache.lucene.index.LeafReaderContext; -import org.apache.solr.common.util.NamedList; -import org.apache.solr.request.SolrQueryRequest; -import org.apache.solr.search.join.BlockJoinFieldFacetAccumulator.AggregatableDocIter; - -/** - * For each collected parent document creates matched block, which is a docSet with matched children and parent doc - * itself. Then updates each BlockJoinFieldFacetAccumulator with the created matched block. - */ -class BlockJoinFacetAccsHolder { - private BlockJoinFieldFacetAccumulator[] blockJoinFieldFacetAccumulators; - private boolean firstSegment = true; - - BlockJoinFacetAccsHolder(SolrQueryRequest req) throws IOException { - String[] facetFieldNames = BlockJoinFacetComponentSupport.getChildFacetFields(req); - assert facetFieldNames != null; - blockJoinFieldFacetAccumulators = new BlockJoinFieldFacetAccumulator[facetFieldNames.length]; - for (int i = 0; i < facetFieldNames.length; i++) { - blockJoinFieldFacetAccumulators[i] = new BlockJoinFieldFacetAccumulator(facetFieldNames[i], req.getSearcher()); - } - } - - - protected void doSetNextReader(LeafReaderContext context) throws IOException { - for (BlockJoinFieldFacetAccumulator blockJoinFieldFacetAccumulator : blockJoinFieldFacetAccumulators) { - if(!firstSegment){ - blockJoinFieldFacetAccumulator.migrateGlobal(); - } - blockJoinFieldFacetAccumulator.setNextReader(context); - } - firstSegment = false; - } - - public void finish() throws IOException { - for (BlockJoinFieldFacetAccumulator blockJoinFieldFacetAccumulator : blockJoinFieldFacetAccumulators) { - blockJoinFieldFacetAccumulator.migrateGlobal(); - } - } - - /** is not used - protected int[] includeParentDoc(int parent) { - final int[] docNums = ArrayUtil.grow(childTracking.getChildDocs(), childTracking.getChildCount()+1); - childTracking.setChildDocs(docNums); // we include parent into block, I'm not sure whether it makes sense - docNums[childTracking.getChildCount()]=parent; - return docNums; - }*/ - - protected void countFacets(final AggregatableDocIter iter) throws IOException { - for (BlockJoinFieldFacetAccumulator blockJoinFieldFacetAccumulator : blockJoinFieldFacetAccumulators) { - blockJoinFieldFacetAccumulator.updateCountsWithMatchedBlock( iter); - } - } - - NamedList getFacets() throws IOException { - NamedList> facets = new NamedList<>(blockJoinFieldFacetAccumulators.length); - for (BlockJoinFieldFacetAccumulator state : blockJoinFieldFacetAccumulators) { - facets.add(state.getFieldName(), state.getFacetValue()); - } - return facets; - } - - -} diff --git a/solr/core/src/java/org/apache/solr/search/join/BlockJoinFacetComponent.java b/solr/core/src/java/org/apache/solr/search/join/BlockJoinFacetComponent.java deleted file mode 100644 index 16f84cc71e4..00000000000 --- a/solr/core/src/java/org/apache/solr/search/join/BlockJoinFacetComponent.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.solr.search.join; - -/** this is just a stub refers to {@link BlockJoinDocSetFacetComponent} to avoid - * changes in configs */ -public class BlockJoinFacetComponent extends BlockJoinDocSetFacetComponent { - -} diff --git a/solr/core/src/java/org/apache/solr/search/join/BlockJoinFacetComponentSupport.java b/solr/core/src/java/org/apache/solr/search/join/BlockJoinFacetComponentSupport.java deleted file mode 100644 index 560e441a923..00000000000 --- a/solr/core/src/java/org/apache/solr/search/join/BlockJoinFacetComponentSupport.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.solr.search.join; - -import java.io.IOException; -import java.util.List; -import java.util.Map; - -import org.apache.lucene.search.BooleanClause; -import org.apache.lucene.search.BooleanQuery; -import org.apache.lucene.search.Query; -import org.apache.lucene.search.join.ToParentBlockJoinQuery; -import org.apache.solr.common.SolrException; -import org.apache.solr.common.params.ShardParams; -import org.apache.solr.common.util.NamedList; -import org.apache.solr.handler.component.ResponseBuilder; -import org.apache.solr.handler.component.SearchComponent; -import org.apache.solr.handler.component.ShardRequest; -import org.apache.solr.handler.component.ShardResponse; -import org.apache.solr.request.SolrQueryRequest; - -abstract class BlockJoinFacetComponentSupport extends SearchComponent { - public static final String CHILD_FACET_FIELD_PARAMETER = "child.facet.field"; - public static final String NO_TO_PARENT_BJQ_MESSAGE = "Block join faceting is allowed with ToParentBlockJoinQuery only"; - public static final String COLLECTOR_CONTEXT_PARAM = "blockJoinFacetCollector"; - - protected void validateQuery(Query query) { - if (!(query instanceof ToParentBlockJoinQuery)) { - if (query instanceof BooleanQuery) { - List clauses = ((BooleanQuery) query).clauses(); - for (BooleanClause clause : clauses) { - if (clause.getQuery() instanceof ToParentBlockJoinQuery) { - return; - } - } - } - throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, NO_TO_PARENT_BJQ_MESSAGE); - } - } - - static String[] getChildFacetFields(SolrQueryRequest req) { - return req.getParams().getParams(CHILD_FACET_FIELD_PARAMETER); - } - - @Override - public void process(ResponseBuilder rb) throws IOException { - if (getChildFacetFields(rb.req) != null) { - BlockJoinFacetAccsHolder blockJoinFacetCollector = (BlockJoinFacetAccsHolder) rb.req.getContext().get(COLLECTOR_CONTEXT_PARAM); - assert blockJoinFacetCollector != null; - NamedList output; - if (isShard(rb)) { - // distributed search, put results into own cell in order not to clash with facet component - output = getChildFacetFields(rb.rsp.getValues(), true); - } else { - // normal process, put results into standard response - output = getFacetFieldsList(rb); - } - mergeFacets(output, blockJoinFacetCollector.getFacets()); - } - } - - private boolean isShard(ResponseBuilder rb) { - return "true".equals(rb.req.getParams().get(ShardParams.IS_SHARD)); - } - - private NamedList getChildFacetFields(NamedList responseValues, boolean createIfAbsent) { - return getNamedListFromList(responseValues, "child_facet_fields", createIfAbsent); - } - - private void mergeFacets(NamedList childFacetFields, NamedList shardFacets) { - if (shardFacets != null) { - for (Map.Entry> nextShardFacet : (Iterable>>) shardFacets) { - String fieldName = nextShardFacet.getKey(); - NamedList collectedFacet = (NamedList) childFacetFields.get(fieldName); - NamedList shardFacet = nextShardFacet.getValue(); - if (collectedFacet == null) { - childFacetFields.add(fieldName, shardFacet); - } else { - mergeFacetValues(collectedFacet, shardFacet); - } - } - } - } - - private void mergeFacetValues(NamedList collectedFacetValue, NamedList shardFacetValue) { - for (Map.Entry nextShardValue : shardFacetValue) { - String facetValue = nextShardValue.getKey(); - Integer shardCount = nextShardValue.getValue(); - int indexOfCollectedValue = collectedFacetValue.indexOf(facetValue, 0); - if (indexOfCollectedValue == -1) { - collectedFacetValue.add(facetValue, shardCount); - } else { - int newCount = collectedFacetValue.getVal(indexOfCollectedValue) + shardCount; - collectedFacetValue.setVal(indexOfCollectedValue, newCount); - } - } - } - - private NamedList getNamedListFromList(NamedList parentList, String name, boolean createIfAbsent) { - NamedList result = null; - if (parentList != null) { - result = (NamedList) parentList.get(name); - if (result == null && createIfAbsent) { - result = new NamedList(); - parentList.add(name, result); - } - } - return result; - } - - @Override - public void handleResponses(ResponseBuilder rb, ShardRequest sreq) { - if ((sreq.purpose & ShardRequest.PURPOSE_GET_TOP_IDS) != 0) { - NamedList collectedChildFacetFields = getChildFacetFields(rb.rsp.getValues(), true); - List responses = sreq.responses; - for (ShardResponse shardResponse : responses) { - NamedList shardChildFacetFields = getChildFacetFields(shardResponse.getSolrResponse().getResponse(), false); - mergeFacets(collectedChildFacetFields, shardChildFacetFields); - } - } - } - - @Override - public void finishStage(ResponseBuilder rb) { - if (rb.stage != ResponseBuilder.STAGE_GET_FIELDS) return; - NamedList childFacetFields = getChildFacetFields(rb.rsp.getValues(), true); - NamedList facetFields = getFacetFieldsList(rb); - for (Map.Entry childFacetField : (Iterable>) childFacetFields) { - facetFields.add(childFacetField.getKey(), childFacetField.getValue()); - } - rb.rsp.getValues().remove("child_facet_fields"); - } - - private NamedList getFacetFieldsList(ResponseBuilder rb) { - NamedList facetCounts = getNamedListFromList(rb.rsp.getValues(), "facet_counts", true); - return getNamedListFromList(facetCounts, "facet_fields", true); - } - - - @Override - public String getDescription() { - return "BlockJoin facet component"; - } -} diff --git a/solr/core/src/java/org/apache/solr/search/join/BlockJoinFacetFilter.java b/solr/core/src/java/org/apache/solr/search/join/BlockJoinFacetFilter.java deleted file mode 100644 index 5d65422c6cc..00000000000 --- a/solr/core/src/java/org/apache/solr/search/join/BlockJoinFacetFilter.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.solr.search.join; - -import java.util.Objects; - -import org.apache.lucene.search.IndexSearcher; -import org.apache.lucene.search.Query; -import org.apache.lucene.search.QueryVisitor; -import org.apache.solr.search.DelegatingCollector; -import org.apache.solr.search.PostFilter; - -class BlockJoinFacetFilter extends Query implements PostFilter { - - public static final int COST = 120; - private DelegatingCollector blockJoinFacetCollector; - - public BlockJoinFacetFilter(DelegatingCollector blockJoinFacetCollector) { - super(); - this.blockJoinFacetCollector = blockJoinFacetCollector; - } - - @Override - public String toString(String field) { - return null; - } - - @Override - public DelegatingCollector getFilterCollector(IndexSearcher searcher) { - return blockJoinFacetCollector; - } - - @Override - public boolean getCache() { - return false; - } - - @Override - public void setCache(boolean cache) { - - } - - @Override - public int getCost() { - return COST; - } - - @Override - public void setCost(int cost) { - - } - - @Override - public boolean getCacheSep() { - return false; - } - - @Override - public void setCacheSep(boolean cacheSep) { - - } - - @Override - public boolean equals(Object other) { - return sameClassAs(other) && - equalsTo(getClass().cast(other)); - } - - private boolean equalsTo(BlockJoinFacetFilter other) { - return Objects.equals(blockJoinFacetCollector, other.blockJoinFacetCollector); - } - - @Override - public int hashCode() { - return classHash() * 31 + blockJoinFacetCollector.hashCode(); - } - - @Override - public void visit(QueryVisitor visitor) { - visitor.visitLeaf(this); - } -} diff --git a/solr/core/src/java/org/apache/solr/search/join/BlockJoinFieldFacetAccumulator.java b/solr/core/src/java/org/apache/solr/search/join/BlockJoinFieldFacetAccumulator.java deleted file mode 100644 index 703307cc2b4..00000000000 --- a/solr/core/src/java/org/apache/solr/search/join/BlockJoinFieldFacetAccumulator.java +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.solr.search.join; - -import java.io.IOException; -import java.util.Arrays; - -import org.apache.lucene.index.DocValues; -import org.apache.lucene.index.LeafReaderContext; -import org.apache.lucene.index.MultiDocValues; -import org.apache.lucene.index.OrdinalMap; -import org.apache.lucene.index.SortedDocValues; -import org.apache.lucene.index.SortedSetDocValues; -import org.apache.lucene.util.ArrayUtil; -import org.apache.lucene.util.BytesRef; -import org.apache.lucene.util.CharsRefBuilder; -import org.apache.lucene.util.LongValues; -import org.apache.solr.common.util.NamedList; -import org.apache.solr.request.DocValuesFacets; -import org.apache.solr.schema.FieldType; -import org.apache.solr.schema.SchemaField; -import org.apache.solr.search.DocIterator; -import org.apache.solr.search.SolrIndexSearcher; - -/** - * This class is responsible for collecting block join facet counts for particular field - */ -class BlockJoinFieldFacetAccumulator { - private String fieldName; - private FieldType fieldType; - private int currentSegment = -1; - // for term lookups only - private SortedSetDocValues topSSDV; - private int[] globalCounts; - private SortedSetDocValues segmentSSDV; - // elems are : facet value counter<<32 | last parent doc num - private long[] segmentAccums = new long[0]; - // for mapping per-segment ords to global ones - private OrdinalMap ordinalMap; - private SchemaField schemaField; - private SortedDocValues segmentSDV; - - BlockJoinFieldFacetAccumulator(String fieldName, SolrIndexSearcher searcher) throws IOException { - this.fieldName = fieldName; - schemaField = searcher.getSchema().getField(fieldName); - fieldType = schemaField.getType(); - ordinalMap = null; - if (schemaField.multiValued()) { - topSSDV = searcher.getSlowAtomicReader().getSortedSetDocValues(fieldName); - if (topSSDV instanceof MultiDocValues.MultiSortedSetDocValues) { - ordinalMap = ((MultiDocValues.MultiSortedSetDocValues) topSSDV).mapping; - } - } else { - SortedDocValues single = searcher.getSlowAtomicReader().getSortedDocValues(fieldName); - if (single instanceof MultiDocValues.MultiSortedDocValues) { - ordinalMap = ((MultiDocValues.MultiSortedDocValues) single).mapping; - } - if (single != null) { - topSSDV = DocValues.singleton(single); - } - } - } - - private boolean initSegmentData(String fieldName, LeafReaderContext leaf) throws IOException { - segmentSSDV = DocValues.getSortedSet(leaf.reader(), fieldName); - segmentAccums = ArrayUtil.grow(segmentAccums, (int)segmentSSDV.getValueCount()+1);//+1 - // zero counts, -1 parent - Arrays.fill(segmentAccums,0,(int)segmentSSDV.getValueCount()+1, 0x00000000ffffffffL); - segmentSDV = DocValues.unwrapSingleton(segmentSSDV); - return segmentSSDV.getValueCount()!=0;// perhaps we need to count "missings"?? - } - - interface AggregatableDocIter extends DocIterator { - void reset(); - /** a key to aggregate the current document */ - int getAggKey(); - - } - static class SortedIntsAggDocIterator implements AggregatableDocIter { - private int[] childDocs; - private int childCount; - private int parentDoc; - private int pos=-1; - - public SortedIntsAggDocIterator(int[] childDocs, int childCount, int parentDoc) { - this.childDocs = childDocs; - this.childCount = childCount; - this.parentDoc = parentDoc; - } - - - @Override - public boolean hasNext() { - return pos segmentSDV.docID()) { - segmentSDV.advance(docNum); - } - - int term; - if (docNum == segmentSDV.docID()) { - term = segmentSDV.ordValue(); - } else { - term = -1; - } - accumulateTermOrd(term, iter.getAggKey()); - //System.out.println("doc# "+docNum+" "+fieldName+" term# "+term+" tick "+Long.toHexString(segmentAccums[1+term])); - } - } else { - for (iter.reset(); iter.hasNext(); ) { - final int docNum = iter.nextDoc(); - if (docNum > segmentSSDV.docID()) { - segmentSSDV.advance(docNum); - } - if (docNum == segmentSSDV.docID()) { - int term = (int) segmentSSDV.nextOrd(); - do { // absent values are designated by term=-1, first iteration counts [0] as "missing", and exit, otherwise it spins - accumulateTermOrd(term, iter.getAggKey()); - } while (term>=0 && (term = (int) segmentSSDV.nextOrd()) >= 0); - } - } - } - } - - String getFieldName() { - return fieldName; - } - - /** copy paste from {@link DocValuesFacets} */ - NamedList getFacetValue() throws IOException { - NamedList facetValue = new NamedList<>(); - final CharsRefBuilder charsRef = new CharsRefBuilder(); // if there is no globs, take segment's ones - for (int i = 1; i< (globalCounts!=null ? globalCounts.length: segmentAccums.length); i++) { - int count = globalCounts!=null ? globalCounts[i] : (int)(segmentAccums [i]>>32); - if (count > 0) { - BytesRef term = topSSDV.lookupOrd(-1 + i); - fieldType.indexedToReadable(term, charsRef); - facetValue.add(charsRef.toString(), count); - } - } - return facetValue; - } - - // @todo we can track in max term nums to loop only changed range while migrating and labeling - private void accumulateTermOrd(int term, int parentDoc) { - long accum = segmentAccums[1+term]; - if(((int)(accum & 0xffffffffL))!=parentDoc) - {// incrementing older 32, reset smaller 32, set them to the new parent - segmentAccums[1+term] = ((accum +(0x1L<<32))&0xffffffffL<<32)|parentDoc; - } - } - - void setNextReader(LeafReaderContext context) throws IOException { - initSegmentData(fieldName, context); - currentSegment = context.ord; - } - - void migrateGlobal(){ - if (currentSegment<0 // no hits - || segmentAccums.length==0 - || ordinalMap==null) { // single segment - return; - } - - if(globalCounts==null){ - // it might be just a single segment - globalCounts = new int[(int) ordinalMap.getValueCount()+ /*[0] for missing*/1]; - }else{ - assert currentSegment>=0; - } - - migrateGlobal(globalCounts, segmentAccums, currentSegment, ordinalMap); - } - - /** folds counts in segment ordinal space (segCounts) into global ordinal space (counts) - * copy paste-from {@link DocValuesFacets#migrateGlobal(int[], int[], int, OrdinalMap)}*/ - void migrateGlobal(int counts[], long segCounts[], int subIndex, OrdinalMap map) { - - final LongValues ordMap = map.getGlobalOrds(subIndex); - // missing count - counts[0] += (int) (segCounts[0]>>32); - - // migrate actual ordinals - for (int ord = 1; ord <= segmentSSDV.getValueCount(); ord++) { - int count = (int) (segCounts[ord]>>32); - if (count != 0) { - counts[1+(int) ordMap.get(ord-1)] += count; - } - } - } -} diff --git a/solr/core/src/java/org/apache/solr/search/join/BlockJoinParentQParser.java b/solr/core/src/java/org/apache/solr/search/join/BlockJoinParentQParser.java index f4bbc9fc7c5..416c9f356ba 100644 --- a/solr/core/src/java/org/apache/solr/search/join/BlockJoinParentQParser.java +++ b/solr/core/src/java/org/apache/solr/search/join/BlockJoinParentQParser.java @@ -85,6 +85,7 @@ public class BlockJoinParentQParser extends FiltersQParser { } public static BitDocIdSetFilterWrapper getCachedFilter(final SolrQueryRequest request, Query parentList) { + @SuppressWarnings("unchecked") SolrCache parentCache = request.getSearcher().getCache(CACHE_NAME); // lazily retrieve from solr cache BitDocIdSetFilterWrapper result; diff --git a/solr/core/src/java/org/apache/solr/search/join/ChildFieldValueSourceParser.java b/solr/core/src/java/org/apache/solr/search/join/ChildFieldValueSourceParser.java index b6312d5f5d2..85bd3d76bcd 100644 --- a/solr/core/src/java/org/apache/solr/search/join/ChildFieldValueSourceParser.java +++ b/solr/core/src/java/org/apache/solr/search/join/ChildFieldValueSourceParser.java @@ -129,10 +129,12 @@ public class ChildFieldValueSourceParser extends ValueSourceParser { return new ToParentBlockJoinSortField(childField.getName(), type, reverse, parentFilter, childFilter) { + @SuppressWarnings("unchecked") @Override public FieldComparator getComparator(int numHits, int sortPos) { final FieldComparator comparator = super.getComparator(numHits, sortPos); - return type ==Type.STRING ? new BytesToStringComparator((FieldComparator) comparator): comparator; + return type ==Type.STRING ? new BytesToStringComparator((FieldComparator) comparator) + : comparator; } }; } @@ -148,7 +150,8 @@ public class ChildFieldValueSourceParser extends ValueSourceParser { } @Override - public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException { + public FunctionValues getValues(@SuppressWarnings("rawtypes") Map context, + LeafReaderContext readerContext) throws IOException { throw new UnsupportedOperationException(this + " is only for sorting"); } } diff --git a/solr/core/src/java/org/apache/solr/search/join/ScoreModeParser.java b/solr/core/src/java/org/apache/solr/search/join/ScoreModeParser.java index 971f23f7536..a303046fc9f 100644 --- a/solr/core/src/java/org/apache/solr/search/join/ScoreModeParser.java +++ b/solr/core/src/java/org/apache/solr/search/join/ScoreModeParser.java @@ -25,6 +25,7 @@ import org.apache.lucene.search.join.ScoreMode; import org.apache.solr.search.SyntaxError; class ScoreModeParser { + @SuppressWarnings("serial") final private static Map lowerAndCapitalCase = Collections.unmodifiableMap( new HashMap() { { diff --git a/solr/core/src/test-files/solr/collection1/conf/schema-blockjoinfacetcomponent.xml b/solr/core/src/test-files/solr/collection1/conf/schema-blockjoinfacetcomponent.xml deleted file mode 100644 index 8db75b61469..00000000000 --- a/solr/core/src/test-files/solr/collection1/conf/schema-blockjoinfacetcomponent.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - id - diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-blockjoinfacetcomponent.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-blockjoinfacetcomponent.xml deleted file mode 100644 index b1145358d22..00000000000 --- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-blockjoinfacetcomponent.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - ${tests.luceneMatchVersion:LATEST} - - - - ${solr.data.dir:} - - - - - - - - ${solr.ulog.dir:} - - - - - - - - - /blockJoinFacetRH - - - blockJoinFacet - - - - - - /blockJoinDocSetFacetRH - - - blockJoinDocSetFacet - - - - diff --git a/solr/core/src/test/org/apache/solr/search/join/BJQParserTest.java b/solr/core/src/test/org/apache/solr/search/join/BJQParserTest.java index 48d64d626e6..c56356324d5 100644 --- a/solr/core/src/test/org/apache/solr/search/join/BJQParserTest.java +++ b/solr/core/src/test/org/apache/solr/search/join/BJQParserTest.java @@ -336,8 +336,10 @@ public class BJQParserTest extends SolrTestCaseJ4 { @Test - public void nullInit() { - new BlockJoinParentQParserPlugin().init(null); + public void nullInit() throws Exception { + final BlockJoinParentQParserPlugin blockJoinParentQParserPlugin = new BlockJoinParentQParserPlugin(); + blockJoinParentQParserPlugin.init(null); + blockJoinParentQParserPlugin.close(); } private final static String eParent[] = new String[]{"//*[@numFound='1']", diff --git a/solr/core/src/test/org/apache/solr/search/join/BlockJoinFacetDistribTest.java b/solr/core/src/test/org/apache/solr/search/join/BlockJoinFacetDistribTest.java deleted file mode 100644 index c4f089652b1..00000000000 --- a/solr/core/src/test/org/apache/solr/search/join/BlockJoinFacetDistribTest.java +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.solr.search.join; - -import java.io.IOException; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.request.CollectionAdminRequest; -import org.apache.solr.client.solrj.response.FacetField; -import org.apache.solr.client.solrj.response.FacetField.Count; -import org.apache.solr.client.solrj.response.QueryResponse; -import org.apache.solr.cloud.SolrCloudTestCase; -import org.apache.solr.common.SolrInputDocument; -import org.apache.solr.common.params.ModifiableSolrParams; -import org.apache.solr.common.util.NamedList; -import org.junit.BeforeClass; -import org.junit.Test; - -public class BlockJoinFacetDistribTest extends SolrCloudTestCase{ - - private static final int defFacetLimit = 10; - private static final String collection = "facetcollection"; - - @BeforeClass - public static void setupCluster() throws Exception { - final Path configDir = Paths.get(TEST_HOME(), "collection1", "conf"); - - String configName = "solrCloudCollectionConfig"; - int nodeCount = 6; - configureCluster(nodeCount) - .addConfig(configName, configDir) - .configure(); - - - Map collectionProperties = new HashMap<>(); - collectionProperties.put("config", "solrconfig-blockjoinfacetcomponent.xml" ); - collectionProperties.put("schema", "schema-blockjoinfacetcomponent.xml"); - - // create a collection holding data for the "to" side of the JOIN - - int shards = 3; - int replicas = 2 ; - CollectionAdminRequest.createCollection(collection, configName, shards, replicas) - .setProperties(collectionProperties) - .process(cluster.getSolrClient()); - - cluster.waitForActiveCollection(collection, shards, shards * replicas); - - } - - final static List colors = Arrays.asList("red","blue","brown","white","black","yellow","cyan","magenta","blur", - "fuchsia", "light","dark","green","grey","don't","know","any","more" ); - final static List sizes = Arrays.asList("s","m","l","xl","xxl","xml","xxxl","3","4","5","6","petite","maxi"); - - @SuppressWarnings("unchecked") - @Test - public void testBJQFacetComponent() throws Exception { - - assert ! colors.removeAll(sizes): "there is no colors in sizes"; - Collections.shuffle(colors,random()); - List matchingColors = colors.subList(0, Math.min(atLeast(random(), 2), colors.size())); - - Map> parentIdsByAttrValue = new HashMap>(){ - @Override - public Set get(Object key) { - return super.get(key)==null && put((String)key, new HashSet<>())==null?super.get(key):super.get(key); - } - }; - - cluster.getSolrClient().deleteByQuery(collection, "*:*"); - - final int parents = atLeast(10); - boolean aggregationOccurs = false; - List parentDocs = new ArrayList<>(); - for(int parent=0; parent resultsResponse = results.getResponse(); - assertNotNull(resultsResponse); - FacetField color_s = results.getFacetField("COLOR_s"); - FacetField size_s = results.getFacetField("SIZE_s"); - - String msg = ""+parentIdsByAttrValue+" "+color_s+" "+size_s; - for (FacetField facet: new FacetField[]{color_s, size_s}) { - for (Count c : facet.getValues()) { - assertEquals(c.getName()+"("+msg+")", - parentIdsByAttrValue.get(c.getName()).size(), c.getCount()); - } - } - - assertEquals(msg , parentIdsByAttrValue.size(),color_s.getValueCount() + size_s.getValueCount()); - - final List> jsonSizes = (List>) - get(resultsResponse, "facets", "children", "sizes", "buckets"); - final List> jsonColors = (List>) - get(resultsResponse, "facets", "children", "colors", "buckets"); - - if (limitJsonColors) { - assertTrue(""+jsonColors, jsonColors.size()<=defFacetLimit); - } - - if (limitJsonSizes) { - assertTrue(""+jsonSizes, jsonSizes.size()<=defFacetLimit); - } - - for (List> vals : new List[] { jsonSizes,jsonColors}) { - int i=0; - for(NamedList tuples: vals) { - String val = (String) get(tuples,"val"); - Number count = (Number) get(tuples,"inprods"); - if (((vals==jsonSizes && limitJsonSizes) || // vals close to the limit are not exact - (vals==jsonColors && limitJsonColors)) && i>=defFacetLimit/2) { - assertTrue(i+ "th "+tuples+". "+vals, - parentIdsByAttrValue.get(val).size()>= count.intValue() && - count.intValue()>0); - } else { - assertEquals(tuples+". "+vals, - parentIdsByAttrValue.get(val).size(),count.intValue()); - } - i++; - } - } - if (!limitJsonColors && !limitJsonSizes) { - assertEquals(""+jsonSizes+jsonColors, parentIdsByAttrValue.size(),jsonSizes.size() + jsonColors.size()); - } - } - - private static Object get(Object nvList, String ... segments) { - for(String segment: segments) { - nvList = ((NamedList) nvList).get(segment); - } - return nvList; - } - - private QueryResponse query(String ... arg) throws SolrServerException, IOException { - ModifiableSolrParams solrParams = new ModifiableSolrParams(); - for(int i=0; i pdocs) throws SolrServerException, IOException { - cluster.getSolrClient().add(collection, pdocs); - } -} diff --git a/solr/core/src/test/org/apache/solr/search/join/BlockJoinFacetRandomTest.java b/solr/core/src/test/org/apache/solr/search/join/BlockJoinFacetRandomTest.java deleted file mode 100644 index 1b2e37b42d1..00000000000 --- a/solr/core/src/test/org/apache/solr/search/join/BlockJoinFacetRandomTest.java +++ /dev/null @@ -1,637 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.solr.search.join; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; - -import org.apache.solr.SolrTestCaseJ4; -import org.apache.solr.common.SolrException; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; - -public class BlockJoinFacetRandomTest extends SolrTestCaseJ4 { - private static String handler; - private static final int NUMBER_OF_PARENTS = 10; - private static final int NUMBER_OF_VALUES = 5; - private static final int NUMBER_OF_CHILDREN = 5; - private static final String[] facetFields = {"brand", "category", "color", "size", "type"}; - private static final String[] otherValues = {"x_", "y_", "z_"}; - public static final String PARENT_VALUE_PREFIX = "prn_"; - public static final String CHILD_VALUE_PREFIX = "chd_"; - - - private static Facet[] facets; - - @BeforeClass - public static void beforeClass() throws Exception { - initCore("solrconfig-blockjoinfacetcomponent.xml", "schema-blockjoinfacetcomponent.xml"); - handler = random().nextBoolean() ? "/blockJoinDocSetFacetRH":"/blockJoinFacetRH"; - facets = createFacets(); - createIndex(); - } - - public static void createIndex() throws Exception { - int i = 0; - List>> blocks = createBlocks(); - for (List> block : blocks) { - List updBlock = new ArrayList<>(); - for (List blockFields : block) { - blockFields.add("id"); - blockFields.add(Integer.toString(i)); - updBlock.add(doc(blockFields.toArray(new String[blockFields.size()]))); - i++; - } - //got xmls for every doc. now nest all into the last one - XmlDoc parentDoc = updBlock.get(updBlock.size() - 1); - parentDoc.xml = parentDoc.xml.replace("", - updBlock.subList(0, updBlock.size() - 1).toString().replaceAll("[\\[\\]]", "") + ""); - assertU(add(parentDoc)); - - if (random().nextBoolean()) { - assertU(commit()); - // force empty segment (actually, this will no longer create an empty segment, only a new segments_n) - if (random().nextBoolean()) { - assertU(commit()); - } - } - } - assertU(commit()); - assertQ(req("q", "*:*"), "//*[@numFound='" + i + "']"); - } - - private static List>> createBlocks() { - List>> blocks = new ArrayList<>(); - for (int i = 0; i < NUMBER_OF_PARENTS; i++) { - List> block = createChildrenBlock(i, facets); - List fieldsList = new LinkedList<>(); - fieldsList.add("parent_s"); - fieldsList.add(parent(i)); - for (Facet facet : facets) { - for (RandomFacetValue facetValue : facet.facetValues) { - RandomParentPosting posting = facetValue.postings[i]; - if (posting.parentHasOwnValue) { - fieldsList.add(facet.getFieldNameForIndex()); - fieldsList.add(facetValue.facetValue); - } else if (facet.multiValued && random().nextBoolean()) { - fieldsList.add(facet.getFieldNameForIndex()); - fieldsList.add(someOtherValue(facet.fieldType)); - } - } - if (facet.additionalValueIsAllowedForParent(i)&&random().nextBoolean()) { - fieldsList.add(facet.getFieldNameForIndex()); - fieldsList.add(someOtherValue(facet.fieldType)); - } - } - block.add(fieldsList); - blocks.add(block); - } - Collections.shuffle(blocks, random()); - return blocks; - } - - private static List> createChildrenBlock(int parentIndex, Facet[] facets) { - List> block = new ArrayList<>(); - for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { - List fieldsList = new LinkedList<>(); - - fieldsList.add("child_s"); - fieldsList.add(child(i)); - fieldsList.add("parentchild_s"); - fieldsList.add(parentChild(parentIndex, i)); - for (Facet facet : facets) { - for (RandomFacetValue facetValue : facet.facetValues) { - RandomParentPosting posting = facetValue.postings[parentIndex]; - if (posting.childrenHaveValue[i]) { - fieldsList.add(facet.getFieldNameForIndex()); - fieldsList.add(facetValue.facetValue); - } else if (facet.multiValued && random().nextBoolean()) { - fieldsList.add(facet.getFieldNameForIndex()); - fieldsList.add(someOtherValue(facet.fieldType)); - } - } - if (facet.additionalValueIsAllowedForChild(parentIndex,i)&&random().nextBoolean()) { - fieldsList.add(facet.getFieldNameForIndex()); - fieldsList.add(someOtherValue(facet.fieldType)); - } - } - block.add(fieldsList); - } - Collections.shuffle(block, random()); - return block; - } - - private static String parent(int docNumber) { - return fieldValue(PARENT_VALUE_PREFIX, docNumber); - } - - private static String child(int docNumber) { - return fieldValue(CHILD_VALUE_PREFIX, docNumber); - } - - private static String someOtherValue(FieldType fieldType) { - int randomValue = random().nextInt(NUMBER_OF_VALUES) + NUMBER_OF_VALUES; - switch (fieldType) { - case String : - int index = random().nextInt(otherValues.length); - return otherValues[index]+randomValue; - case Float: - return createFloatValue(randomValue); - default: - return String.valueOf(randomValue); - - } - - } - - private static String createFloatValue(int intValue) { - return intValue + ".01"; - } - - private static String fieldValue(String valuePrefix, int docNumber) { - return valuePrefix + docNumber; - } - - private static String parentChild(int parentIndex, int childIndex) { - return parent(parentIndex) + "_" + child(childIndex); - } - - @AfterClass - public static void cleanUp() throws Exception { - if (null != h) { - assertU(delQ("*:*")); - optimize(); - assertU((commit())); - } - } - - @Test - public void testValidation() throws Exception { - assertQ("Component is ignored", - req("q", "+parent_s:(prn_1 prn_2)", "qt", handler) - , "//*[@numFound='2']" - , "//doc/str[@name=\"parent_s\"]='prn_1'" - , "//doc/str[@name=\"parent_s\"]='prn_2'" - ); - - assertQEx("Validation exception is expected because query is not ToParentBlockJoinQuery", - BlockJoinFacetComponent.NO_TO_PARENT_BJQ_MESSAGE, - req( - "q", "t", - "df", "name", - "qt", handler, - BlockJoinFacetComponent.CHILD_FACET_FIELD_PARAMETER, facetFields[0] - ), - SolrException.ErrorCode.BAD_REQUEST - ); - - assertQEx("Validation exception is expected because facet field is not defined in schema", - req( - "q", "{!parent which=\"parent_s:[* TO *]\"}child_s:chd_1", - "qt", handler, - BlockJoinFacetComponent.CHILD_FACET_FIELD_PARAMETER, "undefinedField" - ), - SolrException.ErrorCode.BAD_REQUEST - ); - } - - @Test - public void testAllDocs() throws Exception { - int[] randomFacets = getRandomArray(facets.length); - assertQ("Random facets for all docs should be calculated", - req(randomFacetsRequest(null, null, null, null, null, randomFacets)), - expectedResponse(null, null, randomFacets)); - } - - @Test - public void testRandomParentsAllChildren() throws Exception { - int[] randomParents = getRandomArray(NUMBER_OF_PARENTS); - int[] randomFacets = getRandomArray(facets.length); - assertQ("Random facets for random parents should be calculated", - req(randomFacetsRequest(randomParents, null, null, null, null, randomFacets)), - expectedResponse(randomParents, null, randomFacets)); - } - - @Test - public void testRandomChildrenAllParents() throws Exception { - int[] randomChildren = getRandomArray(NUMBER_OF_CHILDREN); - int[] randomFacets = getRandomArray(facets.length); - assertQ("Random facets for all parent docs should be calculated", - req(randomFacetsRequest(null, randomChildren, null, null, null, randomFacets)), - expectedResponse(null, randomChildren, randomFacets)); - } - - @Test - public void testRandomChildrenRandomParents() throws Exception { - int[] randomParents = getRandomArray(NUMBER_OF_PARENTS); - int[] randomChildren = getRandomArray(NUMBER_OF_CHILDREN); - int[] randomFacets = getRandomArray(facets.length); - assertQ("Random facets for all parent docs should be calculated", - req(randomFacetsRequest(randomParents, randomChildren, null, null, null, randomFacets)), - expectedResponse(randomParents, randomChildren, randomFacets)); - } - - @Test - public void testRandomChildrenRandomParentsRandomRelations() throws Exception { - int[] randomParents = getRandomArray(NUMBER_OF_PARENTS); - int[] randomChildren = getRandomArray(NUMBER_OF_CHILDREN); - int[] parentRelations = getRandomArray(NUMBER_OF_PARENTS); - int[] childRelations = getRandomArray(NUMBER_OF_CHILDREN); - int[] randomFacets = getRandomArray(facets.length); - assertQ("Random facets for all parent docs should be calculated", - req(randomFacetsRequest(randomParents, randomChildren, parentRelations, childRelations, null, randomFacets)), - expectedResponse(intersection(randomParents, parentRelations), - intersection(randomChildren, childRelations), randomFacets)); - } - - @Test - public void testRandomFilters() throws Exception { - int[] randomParents = getRandomArray(NUMBER_OF_PARENTS); - int[] randomChildren = getRandomArray(NUMBER_OF_CHILDREN); - int[] parentRelations = getRandomArray(NUMBER_OF_PARENTS); - int[] childRelations = getRandomArray(NUMBER_OF_CHILDREN); - int[] randomParentFilters = getRandomArray(NUMBER_OF_PARENTS); - int[] randomFacets = getRandomArray(facets.length); - assertQ("Random facets for all parent docs should be calculated", - req(randomFacetsRequest(randomParents, randomChildren, parentRelations, childRelations, randomParentFilters, randomFacets)), - expectedResponse(intersection(intersection(randomParents, parentRelations), randomParentFilters), - intersection(randomChildren, childRelations), randomFacets)); - } - - private int[] intersection(int[] firstArray, int[] secondArray) { - Set firstSet = new HashSet<>(); - for (int i : firstArray) { - firstSet.add(i); - } - Set secondSet = new HashSet<>(); - for (int i : secondArray) { - secondSet.add(i); - } - firstSet.retainAll(secondSet); - int[] result = new int[firstSet.size()]; - int i = 0; - for (Integer integer : firstSet) { - result[i++] = integer; - } - return result; - } - - private String[] randomFacetsRequest(int[] parents, int[] children, - int[] parentRelations, int[] childRelations, - int[] parentFilters, int[] facetNumbers) { - List params = new ArrayList<>(Arrays.asList( - "q", parentsQuery(parents), - "qt",handler, - "pq","parent_s:[* TO *]", - "chq", childrenQuery(children, parentRelations, childRelations), - "fq", flatQuery(parentFilters, "parent_s", PARENT_VALUE_PREFIX) - )); - for (int facetNumber : facetNumbers) { - params .add(BlockJoinFacetComponent.CHILD_FACET_FIELD_PARAMETER); - params .add(facets[facetNumber].getFieldNameForIndex()); - } - return params.toArray(new String[params.size()]); - } - - private String parentsQuery(int[] parents) { - String result; - if (parents == null) { - result = "{!parent which=$pq v=$chq}"; - } else { - result = flatQuery(parents, "parent_s", PARENT_VALUE_PREFIX) + " +_query_:\"{!parent which=$pq v=$chq}\""; - } - return result; - } - - private String flatQuery(int[] docNumbers, final String fieldName, String fieldValuePrefix) { - String result; - if (docNumbers == null) { - result = "+" + fieldName + ":[* TO *]"; - } else { - StringBuilder builder = new StringBuilder("+" + fieldName +":("); - if (docNumbers.length == 0) { - builder.append("match_nothing_value"); - } else { - for (int docNumber : docNumbers) { - builder.append(fieldValue(fieldValuePrefix, docNumber)); - builder.append(" "); - } - builder.deleteCharAt(builder.length() - 1); - } - builder.append(")"); - result = builder.toString(); - } - return result; - } - - private String childrenQuery(int[] children, int[] parentRelations, int[] childRelations) { - StringBuilder builder = new StringBuilder(); - builder.append(flatQuery(children, "child_s", CHILD_VALUE_PREFIX)); - if (parentRelations == null) { - if (childRelations == null) { - builder.append(" +parentchild_s:[* TO *]"); - } else { - builder.append(" +parentchild_s:("); - if (childRelations.length == 0) { - builder.append("match_nothing_value"); - } else { - for (int childRelation : childRelations) { - for (int i = 0; i < NUMBER_OF_PARENTS; i++) { - builder.append(parentChild(i, childRelation)); - builder.append(" "); - } - } - builder.deleteCharAt(builder.length() - 1); - } - builder.append(")"); - } - } else { - builder.append(" +parentchild_s:("); - if (parentRelations.length == 0) { - builder.append("match_nothing_value"); - } else { - if (childRelations == null) { - for (int parentRelation : parentRelations) { - for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { - builder.append(parentChild(parentRelation, i)); - builder.append(" "); - } - } - } else if (childRelations.length == 0) { - builder.append("match_nothing_value"); - } else { - for (int parentRelation : parentRelations) { - - for (int childRelation : childRelations) { - builder.append(parentChild(parentRelation, childRelation)); - builder.append(" "); - } - } - builder.deleteCharAt(builder.length() - 1); - } - } - builder.append(")"); - } - return builder.toString(); - } - - private String[] expectedResponse(int[] parents, int[] children, int[] facetNumbers) { - List result = new LinkedList<>(); - if (children != null && children.length == 0) { - result.add("//*[@numFound='" + 0 + "']"); - } else { - if (parents == null) { - result.add("//*[@numFound='" + NUMBER_OF_PARENTS + "']"); - for (int i = 0; i < NUMBER_OF_PARENTS; i++) { - result.add("//doc/str[@name=\"parent_s\"]='" + parent(i) + "'"); - } - } else { - result.add("//*[@numFound='" + parents.length + "']"); - for (int parent : parents) { - result.add("//doc/str[@name=\"parent_s\"]='" + parent(parent) + "'"); - } - } - } - if (facetNumbers != null) { - for (int facetNumber : facetNumbers) { - result.add("//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + facets[facetNumber].getFieldNameForIndex() + "']"); - RandomFacetValue[] facetValues = facets[facetNumber].facetValues; - for (RandomFacetValue facetValue : facetValues) { - int expectedFacetCount = facetValue.getFacetCount(parents, children); - if (expectedFacetCount > 0) { - result.add("//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + - facets[facetNumber].getFieldNameForIndex() + "']/int[@name='" + - facetValue.facetValue + "' and text()='" + expectedFacetCount + "']"); - } - } - } - } - return result.toArray(new String[result.size()]); - } - - private static Facet[] createFacets() { - int[] facetsToCreate = getRandomArray(facetFields.length); - Facet[] facets = new Facet[facetsToCreate.length]; - int i = 0; - for (int facetNumber : facetsToCreate) { - facets[i++] = new Facet(facetFields[facetNumber]); - } - return facets; - } - - private static int[] getRandomArray(int maxNumber) { - int[] buffer = new int[maxNumber]; - int count = 0; - for (int i = 0; i < maxNumber; i++) { - if (random().nextBoolean()) { - buffer[count++] = i; - } - } - int[] result = new int[count]; - System.arraycopy(buffer, 0, result, 0, count); - return result; - } - - private static class Facet { - private String fieldName; - private boolean multiValued = true; - FieldType fieldType; - RandomFacetValue[] facetValues; - - Facet(String fieldName) { - this.fieldName = fieldName; - fieldType = FieldType.values()[random().nextInt(FieldType.values().length)]; - if ( FieldType.String.equals(fieldType)) { - // sortedDocValues are supported for string fields only - multiValued = random().nextBoolean(); - } - - fieldType = FieldType.String; - facetValues = new RandomFacetValue[NUMBER_OF_VALUES]; - for (int i = 0; i < NUMBER_OF_VALUES; i++) { - String value = createRandomValue(i); - facetValues[i] = new RandomFacetValue(value); - } - if (!multiValued) { - makeValuesSingle(); - } - } - - private String createRandomValue(int i) { - switch( fieldType ) { - case String: - return fieldName.substring(0, 2) + "_" + i; - case Float: - return createFloatValue(i); - default: - return String.valueOf(i); - } - } - - String getFieldNameForIndex() { - String multiValuedPostfix = multiValued ? "_multi" : "_single"; - return fieldName + fieldType.fieldPostfix + multiValuedPostfix; - } - - private void makeValuesSingle() { - for ( int i = 0; i < NUMBER_OF_PARENTS; i++) { - List values = getValuesForParent(i); - if ( values.size() > 0) { - int singleValueOrd = values.get(random().nextInt(values.size())); - setSingleValueForParent(i,singleValueOrd); - } - for ( int j=0; j < NUMBER_OF_CHILDREN; j++) { - values = getValuesForChild(i,j); - if ( values.size() > 0 ) { - int singleValueOrd = values.get(random().nextInt(values.size())); - setSingleValueForChild(i, j, singleValueOrd); - } - } - } - } - - private List getValuesForParent(int parentNumber) { - List result = new ArrayList<>(); - for (int i = 0; i getValuesForChild(int parentNumber, int childNumber) { - List result = new ArrayList<>(); - for (int i = 0; i 0); - if (!result) { - if (childNumbers == null) { - for (boolean childHasValue : childrenHaveValue) { - result = childHasValue; - if (result) { - break; - } - } - } else { - for (int child : childNumbers) { - result = childrenHaveValue[child]; - if (result) { - break; - } - } - } - } - return result; - } - } -} diff --git a/solr/core/src/test/org/apache/solr/search/join/BlockJoinFacetSimpleTest.java b/solr/core/src/test/org/apache/solr/search/join/BlockJoinFacetSimpleTest.java deleted file mode 100644 index c4d3a64253e..00000000000 --- a/solr/core/src/test/org/apache/solr/search/join/BlockJoinFacetSimpleTest.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.solr.search.join; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import org.apache.solr.SolrTestCaseJ4; -import org.apache.solr.request.SolrQueryRequest; -import org.junit.BeforeClass; -import org.junit.Test; - -public class BlockJoinFacetSimpleTest extends SolrTestCaseJ4 { - private static String handler; - - @BeforeClass - public static void beforeClass() throws Exception { - initCore("solrconfig-blockjoinfacetcomponent.xml", "schema-blockjoinfacetcomponent.xml"); - handler = random().nextBoolean() ? "/blockJoinDocSetFacetRH":"/blockJoinFacetRH"; - createIndex(); - } - - public static void createIndex() throws Exception { - - final String match; - List docs = Arrays.asList( -// match - match = adoc("id", "10","type_s", "parent","BRAND_s", "Nike").replace("", - ""+ - doc("id", "11","type_s", "child","COLOR_s", "Red","SIZE_s", "XL")+// matches child filter - doc("id", "12","type_s", "child","COLOR_s", "Red","SIZE_s", "XL")+// matches child filter - doc("id", "13","type_s", "child","COLOR_s", "Blue","SIZE_s", "XL")+""), -// mismatch - adoc("id", "100","type_s", "parent","BRAND_s", "Reebok").replace("", - ""+doc("id", "101","type_s", "child","COLOR_s", "Red","SIZE_s", "M")+ - doc("id", "102","type_s", "child","COLOR_s", "Blue","SIZE_s", "XL")+ - doc("id", "104","type_s", "child","COLOR_s", "While","SIZE_s", "XL")+ - doc("id", "105","type_s", "child","COLOR_s", "Green","SIZE_s", "XXXL")+ - "")); - - Collections.shuffle(docs, random()); - for(String d : docs){ - assertU(d); - } - if(random().nextBoolean()){// let's have a deleted doc - if(random().nextBoolean()){ - assertU("let's have two segs",commit()); - } - assertU("overriding matching doc",match); - } - assertU(commit()); - assertQ(req("q", "*:*"), "//*[@numFound='" + 9 + "']"); - } - - @Test - public void testSimple() throws Exception { - //query - // parents - assertQ(req("q", "type_s:parent"), "//*[@numFound='" + 2 + "']"); - - String alt[][] ={ {"q", "{!parent which=\"type_s:parent\"}+COLOR_s:Red +SIZE_s:XL"}, - {"q", "+{!parent which=\"type_s:parent\"}+COLOR_s:Red +BRAND_s:Nike"}, - {"q", "{!parent which=\"type_s:parent\"}+COLOR_s:Red", "fq", "BRAND_s:Nike"}}; - - for(String param[] : alt){ - final List reqParams = new ArrayList<>(Arrays.asList(param)); - reqParams.addAll(Arrays.asList("qt",handler, - "facet", (random().nextBoolean() ? "true":"false"),// it's indifferent to - "child.facet.field", "COLOR_s", - "child.facet.field", "SIZE_s")); - assertQ(req(reqParams.toArray(new String[0])), - "//*[@numFound='" + 1 + "']", - "//lst[@name='COLOR_s']/int[@name='Red'][.='1']", - // "//lst[@name='COLOR_s']/int[@name='Blue'][.='1']", - "count(//lst[@name='COLOR_s']/int)=1", - "//lst[@name='SIZE_s']/int[@name='XL'][.='1']", - "count(//lst[@name='SIZE_s']/int)=1"); - - } - } - - @Test - public void testParentLevelFQExclusion() { - SolrQueryRequest req = req( - "qt", handler, - "q", "{!parent which=type_s:parent}+SIZE_s:XL", - "fq", "{!term f=BRAND_s tag=rbrand}Nike", - "facet", "true", - "facet.field", "BRAND_s", - "child.facet.field", "COLOR_s"); - assertQ("no exclusion, brand facet got only one Nike",req, "//*[@numFound='" + 1 + "']", - "count(//lst[@name='BRAND_s']/int[.='1'])=1"); - - assertQ("nike filter is excluded, expecting both brand in facet",req( - "qt", handler, - "q", "{!parent which=type_s:parent}+SIZE_s:XL", - "fq", "{!term f=BRAND_s tag=rbrand}Nike", - "facet", "true", - "facet.field", "{!ex=rbrand}BRAND_s", - "child.facet.field", "COLOR_s"), - "//*[@numFound='" + 1 + "']", - "count(//lst[@name='BRAND_s']/int[.='1'])=2"); - - } -} diff --git a/solr/core/src/test/org/apache/solr/search/join/TestScoreJoinQPNoScore.java b/solr/core/src/test/org/apache/solr/search/join/TestScoreJoinQPNoScore.java index a780d14c7c4..afa45b9243f 100644 --- a/solr/core/src/test/org/apache/solr/search/join/TestScoreJoinQPNoScore.java +++ b/solr/core/src/test/org/apache/solr/search/join/TestScoreJoinQPNoScore.java @@ -206,6 +206,7 @@ public class TestScoreJoinQPNoScore extends SolrTestCaseJ4 { return " score="+vals[random().nextInt(vals.length)]+" "; } + @SuppressWarnings({"rawtypes", "unchecked"}) @Test public void testRandomJoin() throws Exception { int indexIter=50 * RANDOM_MULTIPLIER; @@ -322,7 +323,7 @@ public class TestScoreJoinQPNoScore extends SolrTestCaseJ4 { final Map ps = ((MapSolrParams)req.getParams()).getMap(); final String q = ps.get("q"); ps.put("q", q.replaceAll("\\}", " cache=false\\}")); - String rsp = h.query(req); + h.query(req); } fail(err); } @@ -331,6 +332,7 @@ public class TestScoreJoinQPNoScore extends SolrTestCaseJ4 { } } + @SuppressWarnings("rawtypes") Map> createJoinMap(Map model, String fromField, String toField) { Map> id_to_id = new HashMap>(); @@ -357,6 +359,7 @@ public class TestScoreJoinQPNoScore extends SolrTestCaseJ4 { } + @SuppressWarnings("rawtypes") Set join(Collection input, Map> joinMap) { Set ids = new HashSet(); for (Doc doc : input) { diff --git a/solr/core/src/test/org/apache/solr/search/join/TestScoreJoinQPScore.java b/solr/core/src/test/org/apache/solr/search/join/TestScoreJoinQPScore.java index 8ce6a274a04..0dc0ccf2f72 100644 --- a/solr/core/src/test/org/apache/solr/search/join/TestScoreJoinQPScore.java +++ b/solr/core/src/test/org/apache/solr/search/join/TestScoreJoinQPScore.java @@ -203,6 +203,7 @@ public class TestScoreJoinQPScore extends SolrTestCaseJ4 { Map metrics = h.getCoreContainer().getMetricManager().registry(h.getCore().getCoreMetricManager().getRegistryName()).getMetrics(); + @SuppressWarnings("rawtypes") MetricsMap mm = (MetricsMap)((SolrMetricManager.GaugeWrapper)metrics.get("CACHE.searcher.queryResultCache")).getGauge(); { Map statPre = mm.getValue(); @@ -258,13 +259,14 @@ public class TestScoreJoinQPScore extends SolrTestCaseJ4 { // this queries are not overlap, with other in this test case. // however it might be better to extract this method into the separate suite // for a while let's nuke a cache content, in case of repetitions + @SuppressWarnings("rawtypes") SolrCache cache = (SolrCache)h.getCore().getInfoRegistry().get("queryResultCache"); cache.clear(); } private ScoreMode not(ScoreMode s) { Random r = random(); - final List l = new ArrayList(Arrays.asList(ScoreMode.values())); + final List l = new ArrayList<>(Arrays.asList(ScoreMode.values())); l.remove(s); return l.get(r.nextInt(l.size())); } diff --git a/solr/core/src/test/org/apache/solr/search/join/another/BJQFilterAccessibleTest.java b/solr/core/src/test/org/apache/solr/search/join/another/BJQFilterAccessibleTest.java index 6764f7596b1..96ac205a9b3 100644 --- a/solr/core/src/test/org/apache/solr/search/join/another/BJQFilterAccessibleTest.java +++ b/solr/core/src/test/org/apache/solr/search/join/another/BJQFilterAccessibleTest.java @@ -45,7 +45,8 @@ public class BJQFilterAccessibleTest extends SolrTestCaseJ4 { try (SolrQueryRequest req = lrf.makeRequest()) { TermQuery childQuery = new TermQuery(new Term("child_s", "l")); Query parentQuery = new WildcardQuery(new Term("parent_s", "*")); - ToParentBlockJoinQuery tpbjq = new ToParentBlockJoinQuery(childQuery, BlockJoinParentQParser.getCachedFilter(req,parentQuery).getFilter(), ScoreMode.Max); + ToParentBlockJoinQuery tpbjq = new ToParentBlockJoinQuery(childQuery, + BlockJoinParentQParser.getCachedFilter(req,parentQuery).getFilter(), ScoreMode.Max); Assert.assertEquals(6, req.getSearcher().search(tpbjq,10).totalHits.value); } } diff --git a/solr/solr-ref-guide/src/blockjoin-faceting.adoc b/solr/solr-ref-guide/src/blockjoin-faceting.adoc deleted file mode 100644 index 94b51108f4d..00000000000 --- a/solr/solr-ref-guide/src/blockjoin-faceting.adoc +++ /dev/null @@ -1,115 +0,0 @@ -= BlockJoin Faceting -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -BlockJoin facets allow you to aggregate children facet counts by their parents. - -It is a common requirement that if a parent document has several children documents, all of them need to increment facet value count only once. This functionality is provided by `BlockJoinDocSetFacetComponent`, and `BlockJoinFacetComponent` just an alias for compatibility. - -CAUTION: This functionality is considered deprecated. Users are encouraged to use `uniqueBlock(\_root_)` aggregation under a `terms` facet in the <>. -If this component is used, it must be explicitly enabled for a request handler in `solrconfig.xml`, in the same way as any other <>. - -This example shows how you could add this search components to `solrconfig.xml` and define it in request handler: - -[source,xml] ----- - - - - - /bjqfacet - - - bjqFacetComponent - - ----- - -This component can be added into any search request handler. This component work with distributed search in SolrCloud mode. - -Documents should be added in children-parent blocks as described in <>. Examples: - -.Sample document -[source,xml] ----- - - - 1 - parent - - 11 - Red - XL - 6 - - - 12 - Red - XL - 7 - - - 13 - Blue - L - 5 - - - - 2 - parent - - 21 - Blue - XL - 6 - - - 22 - Blue - XL - 7 - - - 23 - Red - L - 5 - - - ----- - -Queries are constructed the same way as for a <>. For example: - -[source,text] ----- -http://localhost:8983/solr/bjqfacet?q={!parent which=type_s:parent}SIZE_s:XL&child.facet.field=COLOR_s ----- - -As a result we should have facets for Red(1) and Blue(1), because matches on children `id=11` and `id=12` are aggregated into single hit into parent with `id=1`. - -The key components of the request shown above are: - -`/bjqfacet?`:: -The name of the request handler that has been defined with a block join facet component enabled. - -`q={!parent which=type_s:parent}SIZE_s:XL`:: -The mandatory parent query as a main query. The parent query could also be a subordinate clause in a more complex query. - -`&child.facet.field=COLOR_s`:: -The child document field, which might be repeated many times with several fields, as necessary. diff --git a/solr/solr-ref-guide/src/faceting.adoc b/solr/solr-ref-guide/src/faceting.adoc index efbb0331c60..54731172c95 100644 --- a/solr/solr-ref-guide/src/faceting.adoc +++ b/solr/solr-ref-guide/src/faceting.adoc @@ -1,5 +1,4 @@ = Faceting -:page-children: blockjoin-faceting // Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information diff --git a/solr/solr-ref-guide/src/json-faceting-domain-changes.adoc b/solr/solr-ref-guide/src/json-faceting-domain-changes.adoc index 437c9a22f37..473f82f208f 100644 --- a/solr/solr-ref-guide/src/json-faceting-domain-changes.adoc +++ b/solr/solr-ref-guide/src/json-faceting-domain-changes.adoc @@ -179,7 +179,7 @@ NOTE: While a `query` domain can be combined with an additional domain `filter`, When a collection contains <>, the `blockChildren` or `blockParent` domain options can be used transform an existing domain containing one type of document, into a domain containing the documents with the specified relationship (child or parent of) to the documents from the original domain. -Both of these options work similarly to the corresponding <> by taking in a single String query that exclusively matches all parent documents in the collection. If `blockParent` is used, then the resulting domain will contain all parent documents of the children from the original domain. If `blockChildren` is used, then the resulting domain will contain all child documents of the parents from the original domain. +Both of these options work similarly to the corresponding <> by taking in a single String query that exclusively matches all parent documents in the collection. If `blockParent` is used, then the resulting domain will contain all parent documents of the children from the original domain. If `blockChildren` is used, then the resulting domain will contain all child documents of the parents from the original domain. Quite often facets over child documents needs to be counted in parent documents, this can be done by `uniqueBlock(\_root_)` as described in <>. [source,json,subs="verbatim,callouts"]] ---- diff --git a/solr/solr-ref-guide/src/searching-nested-documents.adoc b/solr/solr-ref-guide/src/searching-nested-documents.adoc index 20edbf55c5d..18e6420d1b4 100644 --- a/solr/solr-ref-guide/src/searching-nested-documents.adoc +++ b/solr/solr-ref-guide/src/searching-nested-documents.adoc @@ -25,7 +25,7 @@ section for more details about schema and index configuration. [NOTE] This section does not show case faceting on nested documents. For nested document faceting, please refer to the -<> section. +<> section. == Query Examples