mirror of https://github.com/apache/lucene.git
parent
c40cd19f62
commit
24afd95902
|
@ -16,6 +16,8 @@
|
|||
*/
|
||||
package org.apache.solr.client.solrj.embedded;
|
||||
|
||||
import static org.apache.solr.common.params.CommonParams.PATH;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
@ -24,6 +26,7 @@ import java.util.Collection;
|
|||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.commons.io.output.ByteArrayOutputStream;
|
||||
import org.apache.solr.client.solrj.SolrClient;
|
||||
|
@ -56,8 +59,6 @@ import org.apache.solr.response.ResultContext;
|
|||
import org.apache.solr.response.SolrQueryResponse;
|
||||
import org.apache.solr.servlet.SolrRequestParsers;
|
||||
|
||||
import static org.apache.solr.common.params.CommonParams.PATH;
|
||||
|
||||
/**
|
||||
* SolrClient that connects directly to a CoreContainer.
|
||||
*
|
||||
|
@ -68,6 +69,21 @@ public class EmbeddedSolrServer extends SolrClient {
|
|||
protected final CoreContainer coreContainer;
|
||||
protected final String coreName;
|
||||
private final SolrRequestParsers _parser;
|
||||
private final RequestWriterSupplier supplier;
|
||||
|
||||
public enum RequestWriterSupplier {
|
||||
JavaBin(() -> new BinaryRequestWriter()), XML(() -> new RequestWriter());
|
||||
|
||||
private Supplier<RequestWriter> supplier;
|
||||
|
||||
private RequestWriterSupplier(final Supplier<RequestWriter> supplier) {
|
||||
this.supplier = supplier;
|
||||
}
|
||||
|
||||
public RequestWriter newRequestWriter() {
|
||||
return supplier.get();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an EmbeddedSolrServer using a given solr home directory
|
||||
|
@ -111,12 +127,30 @@ public class EmbeddedSolrServer extends SolrClient {
|
|||
* @param coreName the core to route requests to by default (optional)
|
||||
*/
|
||||
public EmbeddedSolrServer(CoreContainer coreContainer, String coreName) {
|
||||
this(coreContainer, coreName, RequestWriterSupplier.JavaBin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an EmbeddedSolrServer wrapping a CoreContainer.
|
||||
* <p>
|
||||
* Note that EmbeddedSolrServer will shutdown the wrapped CoreContainer when {@link #close()} is called.
|
||||
*
|
||||
* @param coreContainer
|
||||
* the core container
|
||||
* @param coreName
|
||||
* the core to route requests to by default
|
||||
* @param supplier
|
||||
* the supplier used to create a {@link RequestWriter}
|
||||
*/
|
||||
public EmbeddedSolrServer(CoreContainer coreContainer, String coreName,
|
||||
RequestWriterSupplier supplier) {
|
||||
if (coreContainer == null) {
|
||||
throw new NullPointerException("CoreContainer instance required");
|
||||
}
|
||||
this.coreContainer = coreContainer;
|
||||
this.coreName = coreName;
|
||||
_parser = new SolrRequestParsers(null);
|
||||
this.supplier = supplier;
|
||||
}
|
||||
|
||||
// TODO-- this implementation sends the response to XML and then parses it.
|
||||
|
@ -242,32 +276,41 @@ public class EmbeddedSolrServer extends SolrClient {
|
|||
private Set<ContentStream> getContentStreams(SolrRequest request) throws IOException {
|
||||
if (request.getMethod() == SolrRequest.METHOD.GET) return null;
|
||||
if (request instanceof ContentStreamUpdateRequest) {
|
||||
ContentStreamUpdateRequest csur = (ContentStreamUpdateRequest) request;
|
||||
Collection<ContentStream> cs = csur.getContentStreams();
|
||||
final ContentStreamUpdateRequest csur = (ContentStreamUpdateRequest) request;
|
||||
final Collection<ContentStream> cs = csur.getContentStreams();
|
||||
if (cs != null) return new HashSet<>(cs);
|
||||
}
|
||||
RequestWriter.ContentWriter contentWriter = request.getContentWriter(CommonParams.JAVABIN_MIME);
|
||||
final String cType = contentWriter == null ? CommonParams.JAVABIN_MIME : contentWriter.getContentType();
|
||||
|
||||
return Collections.singleton(new ContentStreamBase() {
|
||||
final RequestWriter.ContentWriter contentWriter = request.getContentWriter(null);
|
||||
|
||||
@Override
|
||||
public InputStream getStream() throws IOException {
|
||||
BAOS baos = new BAOS();
|
||||
if (contentWriter != null) {
|
||||
contentWriter.write(baos);
|
||||
} else {
|
||||
new BinaryRequestWriter().write(request, baos);
|
||||
String cType;
|
||||
final BAOS baos = new BAOS();
|
||||
if (contentWriter != null) {
|
||||
contentWriter.write(baos);
|
||||
cType = contentWriter.getContentType();
|
||||
} else {
|
||||
final RequestWriter rw = supplier.newRequestWriter();
|
||||
cType = rw.getUpdateContentType();
|
||||
rw.write(request, baos);
|
||||
}
|
||||
|
||||
final byte[] buf = baos.toByteArray();
|
||||
if (buf.length > 0) {
|
||||
return Collections.singleton(new ContentStreamBase() {
|
||||
|
||||
@Override
|
||||
public InputStream getStream() throws IOException {
|
||||
return new ByteArrayInputStream(buf);
|
||||
}
|
||||
return new ByteArrayInputStream(baos.toByteArray());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContentType() {
|
||||
return cType;
|
||||
@Override
|
||||
public String getContentType() {
|
||||
return cType;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}
|
||||
|
||||
private JavaBinCodec createJavaBinCodec(final StreamingResponseCallback callback, final BinaryResponseWriter.Resolver resolver) {
|
||||
|
|
|
@ -45,6 +45,7 @@ import org.apache.solr.response.TextResponseWriter;
|
|||
import org.apache.solr.search.QParser;
|
||||
import org.apache.solr.search.function.OrdFieldSource;
|
||||
import org.apache.solr.uninverting.UninvertingReader.Type;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -260,8 +261,8 @@ class BoolFieldSource extends ValueSource {
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public boolean boolVal(int doc) throws IOException {
|
||||
return getOrdForDoc(doc) == trueOrd;
|
||||
}
|
||||
|
@ -298,9 +299,10 @@ class BoolFieldSource extends ValueSource {
|
|||
}
|
||||
|
||||
private static final int hcode = OrdFieldSource.class.hashCode();
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return hcode + field.hashCode();
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -498,6 +498,14 @@
|
|||
</analyzer>
|
||||
</fieldType>
|
||||
<fieldType name="severityType" class="${solr.tests.EnumFieldType}" enumsConfig="enumsConfig.xml" enumName="severity"/>
|
||||
|
||||
<fieldType name="binary" class="solr.BinaryField" />
|
||||
<fieldType name="collation" class="solr.CollationField" language="en" />
|
||||
<fieldType name="externalFile" class="solr.ExternalFileField" />
|
||||
<fieldType name="icuCollation" class="solr.ICUCollationField" locale="en" />
|
||||
<fieldType name="latLonPointSpatial" class="solr.LatLonPointSpatialField" />
|
||||
<fieldType name="randomSort" class="solr.RandomSortField" />
|
||||
<fieldType name="point" class="solr.PointType" subFieldSuffix="_coordinate" />
|
||||
|
||||
<fieldType name="sortable_text" class="solr.SortableTextField">
|
||||
<analyzer>
|
||||
|
@ -632,6 +640,28 @@
|
|||
<field name="dateRemove" type="date" indexed="true" stored="true" multiValued="true"/>
|
||||
<field name="floatRemove" type="float" indexed="true" stored="true" multiValued="true"/>
|
||||
|
||||
<field name="binaryRemove" type="binary" indexed="true" stored="true" multiValued="true"/>
|
||||
<field name="booleanRemove" type="boolean" indexed="true" stored="true" multiValued="true"/>
|
||||
<field name="collationRemove" type="collation" indexed="true" stored="true" multiValued="true"/>
|
||||
<field name="datePointRemove" type="pdate" indexed="true" stored="true" multiValued="true"/>
|
||||
<field name="dateRangeRemove" type="dateRange" indexed="true" stored="true" multiValued="true"/>
|
||||
<field name="doublePointRemove" type="pdouble" indexed="true" stored="true" multiValued="true"/>
|
||||
<field name="externalFileRemove" type="externalFile" indexed="true" stored="true" multiValued="true"/>
|
||||
<field name="floatPointRemove" type="pfloat" indexed="true" stored="true" multiValued="true"/>
|
||||
<field name="icuCollationRemove" type="icuCollation" indexed="true" stored="true" multiValued="true"/>
|
||||
<field name="intPointRemove" type="pint" indexed="true" stored="true" multiValued="true"/>
|
||||
<field name="latLonPointSpatialRemove" type="latLonPointSpatial" indexed="true" stored="true" multiValued="true"/>
|
||||
<field name="latLonRemove" type="location" indexed="true" stored="true" multiValued="true"/>
|
||||
<field name="longPointRemove" type="plong" indexed="true" stored="true" multiValued="true"/>
|
||||
<field name="point_0_coordinate" type="float" indexed="true" stored="true" multiValued="true"/>
|
||||
<field name="point_1_coordinate" type="float" indexed="true" stored="true" multiValued="true"/>
|
||||
<field name="pointRemove" type="point" indexed="true" stored="true" multiValued="true"/>
|
||||
<field name="randomSortRemove" type="randomSort" indexed="true" stored="true" multiValued="true"/>
|
||||
<field name="spatialRecursivePrefixTreeRemove" type="location_rpt" indexed="true" stored="true" multiValued="true"/>
|
||||
<field name="stringRemove" type="string" indexed="true" stored="true" multiValued="true"/>
|
||||
<field name="textRemove" type="text" indexed="true" stored="true" multiValued="true"/>
|
||||
<field name="uuidRemove" type="uuid" indexed="true" stored="true" multiValued="true"/>
|
||||
|
||||
<field name="nopositionstext" type="nopositions" indexed="true" stored="true"/>
|
||||
|
||||
<field name="tlong" type="tlong" indexed="true" stored="true"/>
|
||||
|
|
|
@ -0,0 +1,427 @@
|
|||
/*
|
||||
* 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.update.processor;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.hasItems;
|
||||
import static org.hamcrest.CoreMatchers.not;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.curator.shaded.com.google.common.collect.Lists;
|
||||
import org.apache.solr.EmbeddedSolrServerTestBase;
|
||||
import org.apache.solr.client.solrj.SolrServerException;
|
||||
import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer;
|
||||
import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer.RequestWriterSupplier;
|
||||
import org.apache.solr.common.util.ByteArrayUtf8CharSequence;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
public abstract class AbstractAtomicUpdatesMultivalueTestBase extends EmbeddedSolrServerTestBase {
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception {
|
||||
initCore("solrconfig.xml", "schema.xml");
|
||||
}
|
||||
|
||||
@Before
|
||||
public void before() throws SolrServerException, IOException {
|
||||
getSolrClient().deleteByQuery("*:*");
|
||||
}
|
||||
|
||||
abstract RequestWriterSupplier getRequestWriterSupplier();
|
||||
|
||||
@Override
|
||||
public synchronized EmbeddedSolrServer getSolrClient() {
|
||||
return new EmbeddedSolrServer(h.getCoreContainer(), DEFAULT_CORE_NAME, getRequestWriterSupplier()) {
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
// do not close core container
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static void assertQR(final String fieldName, final String queryValue, final int numFound) {
|
||||
assertQ(req("q", fieldName + ":" + queryValue, "indent", "true"), "//result[@numFound = '" + numFound + "']");
|
||||
}
|
||||
|
||||
private void runTestForField(final String fieldName, final Object[] values, final String[] queries,
|
||||
final Optional<Function<Object,Object>> valueConverter)
|
||||
throws SolrServerException, IOException {
|
||||
|
||||
final Function<Object,Object> vc = valueConverter.orElse(o -> o);
|
||||
|
||||
getSolrClient().add(Arrays.asList(
|
||||
sdoc("id", "20000", fieldName, Arrays.asList(values[0], values[1], values[2])),
|
||||
sdoc("id", "20001", fieldName, Arrays.asList(values[1], values[2], values[3]))));
|
||||
getSolrClient().commit(true, true);
|
||||
|
||||
if (queries != null) {
|
||||
assertQR(fieldName, queries[0], 1);
|
||||
assertQR(fieldName, queries[1], 2);
|
||||
assertQR(fieldName, queries[2], 2);
|
||||
assertQR(fieldName, queries[3], 1);
|
||||
}
|
||||
|
||||
Collection<Object> fieldValues = getSolrClient().getById("20000").getFieldValues(fieldName);
|
||||
assertEquals(3, fieldValues.size());
|
||||
assertThat(fieldValues, hasItems(vc.apply(values[0]), vc.apply(values[1]), vc.apply(values[2])));
|
||||
assertThat(fieldValues, not(hasItems(vc.apply(values[3]))));
|
||||
fieldValues = getSolrClient().getById("20001").getFieldValues(fieldName);
|
||||
assertEquals(3, fieldValues.size());
|
||||
assertThat(fieldValues, hasItems(vc.apply(values[1]), vc.apply(values[2]), vc.apply(values[3])));
|
||||
assertThat(fieldValues, not(hasItems(vc.apply(values[0]))));
|
||||
|
||||
getSolrClient().add(sdoc("id", "20000", fieldName, ImmutableMap.of("remove",
|
||||
Lists.newArrayList(values[0]))));
|
||||
getSolrClient().commit(true, true);
|
||||
|
||||
if (queries != null) {
|
||||
assertQR(fieldName, queries[0], 0);
|
||||
assertQR(fieldName, queries[1], 2);
|
||||
assertQR(fieldName, queries[2], 2);
|
||||
assertQR(fieldName, queries[3], 1);
|
||||
}
|
||||
|
||||
fieldValues = getSolrClient().getById("20000").getFieldValues(fieldName);
|
||||
assertEquals(2, fieldValues.size());
|
||||
assertThat(fieldValues, hasItems(vc.apply(values[1]), vc.apply(values[2])));
|
||||
assertThat(fieldValues, not(hasItems(vc.apply(values[0]), vc.apply(values[3]))));
|
||||
fieldValues = getSolrClient().getById("20001").getFieldValues(fieldName);
|
||||
assertEquals(3, fieldValues.size());
|
||||
assertThat(fieldValues, hasItems(vc.apply(values[1]), vc.apply(values[2]), vc.apply(values[3])));
|
||||
assertThat(fieldValues, not(hasItems(vc.apply(values[0]))));
|
||||
|
||||
getSolrClient().add(sdoc("id", "20001", fieldName, ImmutableMap.of("remove",
|
||||
Lists.newArrayList(values[0], values[1], values[2]))));
|
||||
getSolrClient().commit(true, true);
|
||||
|
||||
if (queries != null) {
|
||||
assertQR(fieldName, queries[0], 0);
|
||||
assertQR(fieldName, queries[1], 1);
|
||||
assertQR(fieldName, queries[2], 1);
|
||||
assertQR(fieldName, queries[3], 1);
|
||||
}
|
||||
|
||||
fieldValues = getSolrClient().getById("20000").getFieldValues(fieldName);
|
||||
assertEquals(2, fieldValues.size());
|
||||
assertThat(fieldValues, hasItems(vc.apply(values[1]), vc.apply(values[2])));
|
||||
assertThat(fieldValues, not(hasItems(vc.apply(values[0]), vc.apply(values[3]))));
|
||||
fieldValues = getSolrClient().getById("20001").getFieldValues(fieldName);
|
||||
assertEquals(1, fieldValues.size());
|
||||
assertThat(fieldValues, hasItems(vc.apply(values[3])));
|
||||
assertThat(fieldValues, not(hasItems(vc.apply(values[0]), vc.apply(values[1]), vc.apply(values[2]))));
|
||||
|
||||
getSolrClient().add(Arrays.asList(sdoc("id", "20000", fieldName, ImmutableMap.of("add",
|
||||
Lists.newArrayList(values[0]), "remove", Lists.newArrayList(values[1], values[2]))),
|
||||
sdoc("id", "20001", fieldName,
|
||||
ImmutableMap.of("add", Lists.newArrayList(values[0]), "remove", Lists.newArrayList(values[3])))));
|
||||
getSolrClient().commit(true, true);
|
||||
|
||||
if (queries != null) {
|
||||
assertQR(fieldName, queries[0], 2);
|
||||
assertQR(fieldName, queries[1], 0);
|
||||
assertQR(fieldName, queries[2], 0);
|
||||
assertQR(fieldName, queries[3], 0);
|
||||
}
|
||||
|
||||
fieldValues = getSolrClient().getById("20000").getFieldValues(fieldName);
|
||||
assertEquals(1, fieldValues.size());
|
||||
assertThat(fieldValues, hasItems(vc.apply(values[0])));
|
||||
assertThat(fieldValues, not(hasItems(vc.apply(values[1]), vc.apply(values[2]), vc.apply(values[3]))));
|
||||
fieldValues = getSolrClient().getById("20001").getFieldValues(fieldName);
|
||||
assertEquals(1, fieldValues.size());
|
||||
assertThat(fieldValues, hasItems(vc.apply(values[0])));
|
||||
assertThat(fieldValues, not(hasItems(vc.apply(values[1]), vc.apply(values[2]), vc.apply(values[3]))));
|
||||
|
||||
getSolrClient().add(Arrays.asList(sdoc("id", "20000", fieldName, ImmutableMap.of("set",
|
||||
Lists.newArrayList(values[0], values[1], values[2], values[3]))), sdoc("id", "20001", fieldName,
|
||||
ImmutableMap.of("set",
|
||||
Lists.newArrayList(values[0], values[1], values[2], values[3])))));
|
||||
getSolrClient().commit(true, true);
|
||||
|
||||
if (queries != null) {
|
||||
assertQR(fieldName, queries[0], 2);
|
||||
assertQR(fieldName, queries[1], 2);
|
||||
assertQR(fieldName, queries[2], 2);
|
||||
assertQR(fieldName, queries[3], 2);
|
||||
}
|
||||
|
||||
fieldValues = getSolrClient().getById("20000").getFieldValues(fieldName);
|
||||
assertEquals(4, fieldValues.size());
|
||||
assertThat(fieldValues,
|
||||
hasItems(vc.apply(values[0]), vc.apply(values[1]), vc.apply(values[2]), vc.apply(values[3])));
|
||||
fieldValues = getSolrClient().getById("20001").getFieldValues(fieldName);
|
||||
assertEquals(4, fieldValues.size());
|
||||
assertThat(fieldValues,
|
||||
hasItems(vc.apply(values[0]), vc.apply(values[1]), vc.apply(values[2]), vc.apply(values[3])));
|
||||
}
|
||||
|
||||
private String[] toStringArray(final Object[] values) {
|
||||
return Arrays.stream(values).map(v -> v.toString()).collect(Collectors.toList()).toArray(new String[] {});
|
||||
}
|
||||
|
||||
private void runTestForFieldWithQuery(final String fieldName, final Object[] values)
|
||||
throws SolrServerException, IOException {
|
||||
runTestForField(fieldName, values, toStringArray(values), Optional.empty());
|
||||
}
|
||||
|
||||
private void runTestForFieldWithQuery(final String fieldName, final Object[] values, final String[] queries)
|
||||
throws SolrServerException, IOException {
|
||||
runTestForField(fieldName, values, queries, Optional.empty());
|
||||
}
|
||||
|
||||
private void runTestForFieldWithQuery(final String fieldName, final Object[] values, final String[] queries,
|
||||
final Function<Object,Object> valueConverter)
|
||||
throws SolrServerException, IOException {
|
||||
runTestForField(fieldName, values, queries, Optional.of(valueConverter));
|
||||
}
|
||||
|
||||
private void runTestForFieldWithoutQuery(final String fieldName, final Object[] values)
|
||||
throws SolrServerException, IOException {
|
||||
runTestForField(fieldName, values, null, Optional.empty());
|
||||
}
|
||||
|
||||
@Test
|
||||
@AwaitsFix(bugUrl = "https://issues.apache.org/jira/browse/SOLR-13762")
|
||||
public void testMultivalueBinaryField() throws SolrServerException, IOException {
|
||||
runTestForFieldWithoutQuery("binaryRemove",
|
||||
new byte[][] {new byte[] {0}, new byte[] {1}, new byte[] {2}, new byte[] {3}});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultivalueBooleanField() throws SolrServerException, IOException {
|
||||
|
||||
final String fieldName = "booleanRemove";
|
||||
|
||||
getSolrClient().add(Arrays.asList(
|
||||
sdoc("id", "20000", fieldName, Lists.newArrayList(true, false)),
|
||||
sdoc("id", "20001", fieldName, Lists.newArrayList(false, true))));
|
||||
getSolrClient().commit(true, true);
|
||||
|
||||
assertQR(fieldName, "true", 2);
|
||||
assertQR(fieldName, "false", 2);
|
||||
|
||||
Collection<Object> fieldValues = getSolrClient().getById("20000").getFieldValues(fieldName);
|
||||
assertEquals(2, fieldValues.size());
|
||||
assertThat(fieldValues, hasItems(true, false));
|
||||
fieldValues = getSolrClient().getById("20001").getFieldValues(fieldName);
|
||||
assertEquals(2, fieldValues.size());
|
||||
assertThat(fieldValues, hasItems(true, false));
|
||||
|
||||
getSolrClient().add(sdoc("id", "20000", fieldName, ImmutableMap.of("remove",
|
||||
Lists.newArrayList(false))));
|
||||
getSolrClient().commit(true, true);
|
||||
|
||||
assertQR(fieldName, "true", 2);
|
||||
assertQR(fieldName, "false", 1);
|
||||
|
||||
fieldValues = getSolrClient().getById("20000").getFieldValues(fieldName);
|
||||
assertEquals(1, fieldValues.size());
|
||||
assertThat(fieldValues, hasItems(true));
|
||||
fieldValues = getSolrClient().getById("20001").getFieldValues(fieldName);
|
||||
assertEquals(2, fieldValues.size());
|
||||
assertThat(fieldValues, hasItems(true, false));
|
||||
|
||||
getSolrClient().add(sdoc("id", "20001", fieldName, ImmutableMap.of("remove",
|
||||
Lists.newArrayList(true, false))));
|
||||
getSolrClient().commit(true, true);
|
||||
|
||||
assertQR(fieldName, "true", 1);
|
||||
assertQR(fieldName, "false", 0);
|
||||
|
||||
fieldValues = getSolrClient().getById("20000").getFieldValues(fieldName);
|
||||
assertEquals(1, fieldValues.size());
|
||||
assertThat(fieldValues, hasItems(true));
|
||||
assertThat(fieldValues, not(hasItems(false)));
|
||||
fieldValues = getSolrClient().getById("20001").getFieldValues(fieldName);
|
||||
assertNull(fieldValues);
|
||||
|
||||
getSolrClient().add(Arrays.asList(sdoc("id", "20000", fieldName, ImmutableMap.of("add",
|
||||
Lists.newArrayList(false, false)))));
|
||||
getSolrClient().commit(true, true);
|
||||
|
||||
assertQR(fieldName, "true", 1);
|
||||
assertQR(fieldName, "false", 1);
|
||||
|
||||
fieldValues = getSolrClient().getById("20000").getFieldValues(fieldName);
|
||||
assertEquals(3, fieldValues.size());
|
||||
assertThat(fieldValues, hasItems(true, false));
|
||||
fieldValues = getSolrClient().getById("20001").getFieldValues(fieldName);
|
||||
assertNull(fieldValues);
|
||||
|
||||
getSolrClient().add(Arrays.asList(sdoc("id", "20000", fieldName, ImmutableMap.of("set",
|
||||
Lists.newArrayList(true, false))), sdoc("id", "20001", fieldName,
|
||||
ImmutableMap.of("set",
|
||||
Lists.newArrayList(false, true)))));
|
||||
getSolrClient().commit(true, true);
|
||||
|
||||
assertQR(fieldName, "true", 2);
|
||||
assertQR(fieldName, "false", 2);
|
||||
|
||||
fieldValues = getSolrClient().getById("20000").getFieldValues(fieldName);
|
||||
assertEquals(2, fieldValues.size());
|
||||
assertThat(fieldValues, hasItems(true, false));
|
||||
fieldValues = getSolrClient().getById("20001").getFieldValues(fieldName);
|
||||
assertEquals(2, fieldValues.size());
|
||||
assertThat(fieldValues, hasItems(true, false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultivalueCollationField() throws SolrServerException, IOException {
|
||||
runTestForFieldWithQuery("collationRemove", new String[] {"cf1", "cf2", "cf3", "cf4"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultivalueDatePointField() throws SolrServerException, IOException {
|
||||
|
||||
final String s1 = "1980-01-01T00:00:00Z";
|
||||
final Date d1 = Date.from(ZonedDateTime.parse(s1).toInstant());
|
||||
final String s2 = "1990-01-01T00:00:00Z";
|
||||
final Date d2 = Date.from(ZonedDateTime.parse(s2).toInstant());
|
||||
final String s3 = "2000-01-01T00:00:00Z";
|
||||
final Date d3 = Date.from(ZonedDateTime.parse(s3).toInstant());
|
||||
final String s4 = "2010-01-01T00:00:00Z";
|
||||
final Date d4 = Date.from(ZonedDateTime.parse(s4).toInstant());
|
||||
|
||||
runTestForFieldWithQuery("datePointRemove", new Date[] {d1, d2, d3, d4},
|
||||
new String[] {"\"" + s1 + "\"", "\"" + s2 + "\"", "\"" + s3 + "\"", "\"" + s4 + "\""});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultivalueDateRangeField() throws SolrServerException, IOException {
|
||||
|
||||
final String s1 = "1980-01-01T00:00:00Z";
|
||||
final String s2 = "1990-01-01T00:00:00Z";
|
||||
final String s3 = "2000-01-01T00:00:00Z";
|
||||
final String s4 = "2010-01-01T00:00:00Z";
|
||||
|
||||
runTestForFieldWithQuery("dateRangeRemove", new String[] {s1, s2, s3, s4},
|
||||
new String[] {"\"" + s1 + "\"", "\"" + s2 + "\"", "\"" + s3 + "\"", "\"" + s4 + "\""});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultivalueDoublePointField() throws SolrServerException, IOException {
|
||||
runTestForFieldWithQuery("doublePointRemove", new Double[] {1.0d, 2.0d, 3.0d, 4.0d});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultivalueEnumField() throws SolrServerException, IOException {
|
||||
runTestForFieldWithQuery("enumRemove_sev_enum", new Object[] {"Low", "Medium", "High", "Critical"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultivalueEnumFieldWithNumbers() throws SolrServerException, IOException {
|
||||
final Object[] values = new Object[] {"Low", "Medium", "High", 11};
|
||||
runTestForFieldWithQuery("enumRemove_sev_enum", values, toStringArray(values), o -> {
|
||||
if (Integer.valueOf(11).equals(o)) {
|
||||
return "Critical";
|
||||
} else {
|
||||
return o;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultivalueExternalFileField() throws SolrServerException, IOException {
|
||||
runTestForFieldWithoutQuery("externalFileRemove",
|
||||
new String[] {"file1.txt", "file2.txt", "file3.txt", "file4.txt"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultivalueFloatPointField() throws SolrServerException, IOException {
|
||||
runTestForFieldWithQuery("floatPointRemove", new Float[] {1.0f, 2.0f, 3.0f, 4.0f});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultivalueICUCollationField() throws SolrServerException, IOException {
|
||||
runTestForFieldWithQuery("icuCollationRemove", new String[] {"iuccf1", "icucf2", "icucf3", "icucf4"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultivalueIntPointField() throws SolrServerException, IOException {
|
||||
runTestForFieldWithQuery("intPointRemove", new Integer[] {1, 2, 3, 4});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultivalueLatLonPointSpatialField() throws SolrServerException, IOException {
|
||||
runTestForFieldWithoutQuery("latLonPointSpatialRemove",
|
||||
new String[] {"1.0,-1.0", "2.0,-2.0", "3.0,-3.0", "4.0,-4.0"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultivalueLatLonField() throws SolrServerException, IOException {
|
||||
runTestForFieldWithQuery("latLonRemove", new String[] {"1.0,-1.0", "2.0,-2.0", "3.0,-3.0", "4.0,-4.0"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultivalueLongPointField() throws SolrServerException, IOException {
|
||||
runTestForFieldWithQuery("longPointRemove", new Long[] {1l, 2l, 3l, 4l});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultivaluePointField() throws SolrServerException, IOException {
|
||||
runTestForFieldWithQuery("pointRemove", new String[] {"1,1", "2,2", "3,3", "4,4"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultivalueRandomSortField() throws SolrServerException, IOException {
|
||||
runTestForFieldWithQuery("randomSortRemove", new String[] {"rsf1", "rsf2", "rsf3", "rsf4"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultivalueSpatialRecursivePrefixTreeFieldType() throws SolrServerException, IOException {
|
||||
runTestForFieldWithoutQuery("spatialRecursivePrefixTreeRemove", new String[] {"1,1", "2,2", "3,3", "4,4"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultivalueStringField() throws SolrServerException, IOException {
|
||||
runTestForFieldWithQuery("stringRemove", new String[] {"str1", "str2", "str3", "str4"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultivalueStringFieldUsingCharSequence() throws SolrServerException, IOException {
|
||||
final ByteArrayUtf8CharSequence[] values = new ByteArrayUtf8CharSequence[] {new ByteArrayUtf8CharSequence("str1"),
|
||||
new ByteArrayUtf8CharSequence("str2"),
|
||||
new ByteArrayUtf8CharSequence("str3"), new ByteArrayUtf8CharSequence("str4")};
|
||||
runTestForFieldWithQuery("stringRemove", values, toStringArray(values), o -> o.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultivalueTextField() throws SolrServerException, IOException {
|
||||
runTestForFieldWithQuery("textRemove", new String[] {"text1", "text2", "text3", "text4"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultivalueUUIDField() throws SolrServerException, IOException {
|
||||
final String[] values = new String[] {UUID.randomUUID().toString(), UUID.randomUUID().toString(),
|
||||
UUID.randomUUID().toString(), UUID.randomUUID().toString()};
|
||||
runTestForFieldWithQuery("uuidRemove", values);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* 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.update.processor;
|
||||
|
||||
import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer.RequestWriterSupplier;
|
||||
|
||||
public class JavaBinAtomicUpdateMultivalueTest extends AbstractAtomicUpdatesMultivalueTestBase {
|
||||
|
||||
@Override
|
||||
RequestWriterSupplier getRequestWriterSupplier() {
|
||||
return RequestWriterSupplier.JavaBin;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* 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.update.processor;
|
||||
|
||||
import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer.RequestWriterSupplier;
|
||||
|
||||
public class XMLAtomicUpdateMultivalueTest extends AbstractAtomicUpdatesMultivalueTestBase {
|
||||
|
||||
@Override
|
||||
RequestWriterSupplier getRequestWriterSupplier() {
|
||||
return RequestWriterSupplier.XML;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,592 @@
|
|||
/*
|
||||
* 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.client.solrj.request.json;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
import org.apache.solr.EmbeddedSolrServerTestBase;
|
||||
import org.apache.solr.SolrTestCaseJ4.SuppressSSL;
|
||||
import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer;
|
||||
import org.apache.solr.client.solrj.request.AbstractUpdateRequest;
|
||||
import org.apache.solr.client.solrj.request.ContentStreamUpdateRequest;
|
||||
import org.apache.solr.client.solrj.response.QueryResponse;
|
||||
import org.apache.solr.client.solrj.response.UpdateResponse;
|
||||
import org.apache.solr.client.solrj.response.json.BucketJsonFacet;
|
||||
import org.apache.solr.client.solrj.response.json.NestableJsonFacet;
|
||||
import org.apache.solr.common.SolrDocumentList;
|
||||
import org.apache.solr.util.ExternalPaths;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
@SuppressSSL
|
||||
public class DirectJsonQueryRequestFacetingEmbeddedTest extends EmbeddedSolrServerTestBase {
|
||||
|
||||
private static final String COLLECTION_NAME = "techproducts";
|
||||
private static final int NUM_TECHPRODUCTS_DOCS = 32;
|
||||
private static final int NUM_IN_STOCK = 17;
|
||||
private static final int NUM_ELECTRONICS = 12;
|
||||
private static final int NUM_CURRENCY = 4;
|
||||
private static final int NUM_MEMORY = 3;
|
||||
private static final int NUM_CORSAIR = 3;
|
||||
private static final int NUM_BELKIN = 2;
|
||||
private static final int NUM_CANON = 2;
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception {
|
||||
final String sourceHome = ExternalPaths.SOURCE_HOME;
|
||||
|
||||
final File tempSolrHome = LuceneTestCase.createTempDir().toFile();
|
||||
FileUtils.copyFileToDirectory(new File(sourceHome, "server/solr/solr.xml"), tempSolrHome);
|
||||
final File collectionDir = new File(tempSolrHome, COLLECTION_NAME);
|
||||
FileUtils.forceMkdir(collectionDir);
|
||||
final File configSetDir = new File(sourceHome, "server/solr/configsets/sample_techproducts_configs/conf");
|
||||
FileUtils.copyDirectoryToDirectory(configSetDir, collectionDir);
|
||||
|
||||
final Properties props = new Properties();
|
||||
props.setProperty("name", COLLECTION_NAME);
|
||||
|
||||
try (Writer writer = new OutputStreamWriter(FileUtils.openOutputStream(new File(collectionDir, "core.properties")),
|
||||
"UTF-8");) {
|
||||
props.store(writer, null);
|
||||
}
|
||||
|
||||
final String config = tempSolrHome.getAbsolutePath() + "/" + COLLECTION_NAME + "/conf/solrconfig.xml";
|
||||
final String schema = tempSolrHome.getAbsolutePath() + "/" + COLLECTION_NAME + "/conf/managed-schema";
|
||||
initCore(config, schema, tempSolrHome.getAbsolutePath(), COLLECTION_NAME);
|
||||
|
||||
client = new EmbeddedSolrServer(h.getCoreContainer(), COLLECTION_NAME) {
|
||||
@Override
|
||||
public void close() {
|
||||
// do not close core container
|
||||
}
|
||||
};
|
||||
|
||||
ContentStreamUpdateRequest up = new ContentStreamUpdateRequest("/update");
|
||||
up.setParam("collection", COLLECTION_NAME);
|
||||
up.addFile(getFile("solrj/techproducts.xml"), "application/xml");
|
||||
up.setAction(AbstractUpdateRequest.ACTION.COMMIT, true, true);
|
||||
UpdateResponse updateResponse = up.process(client);
|
||||
assertEquals(0, updateResponse.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleTermsFacet() throws Exception {
|
||||
final String jsonBody = String.join("\n", "{",
|
||||
" 'query': '*:*',",
|
||||
" 'facet': {",
|
||||
" 'top_cats': {",
|
||||
" 'type': 'terms',",
|
||||
" 'field': 'cat',",
|
||||
" 'limit': 3",
|
||||
" }",
|
||||
" }",
|
||||
"}");
|
||||
final DirectJsonQueryRequest request = new DirectJsonQueryRequest(jsonBody);
|
||||
|
||||
QueryResponse response = request.process(getSolrClient(), COLLECTION_NAME);
|
||||
|
||||
assertExpectedDocumentsFoundAndReturned(response, NUM_TECHPRODUCTS_DOCS, 10);
|
||||
final NestableJsonFacet topLevelFacetData = response.getJsonFacetingResponse();
|
||||
assertEquals(NUM_TECHPRODUCTS_DOCS, topLevelFacetData.getCount());
|
||||
assertHasFacetWithBucketValues(topLevelFacetData, "top_cats",
|
||||
new FacetBucket("electronics", NUM_ELECTRONICS),
|
||||
new FacetBucket("currency", NUM_CURRENCY),
|
||||
new FacetBucket("memory", NUM_MEMORY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiTermsFacet() throws Exception {
|
||||
final String jsonBody = String.join("\n", "{",
|
||||
" 'query': '*:*',",
|
||||
" 'facet': {",
|
||||
" 'top_cats': {",
|
||||
" 'type': 'terms',",
|
||||
" 'field': 'cat',",
|
||||
" 'limit': 3",
|
||||
" },",
|
||||
" 'top_manufacturers': {",
|
||||
" 'type': 'terms',",
|
||||
" 'field': 'manu_id_s',",
|
||||
" 'limit': 3",
|
||||
" }",
|
||||
" }",
|
||||
"}");
|
||||
final DirectJsonQueryRequest request = new DirectJsonQueryRequest(jsonBody);
|
||||
|
||||
QueryResponse response = request.process(getSolrClient(), COLLECTION_NAME);
|
||||
|
||||
assertExpectedDocumentsFoundAndReturned(response, NUM_TECHPRODUCTS_DOCS, 10);
|
||||
final NestableJsonFacet topLevelFacetData = response.getJsonFacetingResponse();
|
||||
assertEquals(NUM_TECHPRODUCTS_DOCS, topLevelFacetData.getCount());
|
||||
assertHasFacetWithBucketValues(topLevelFacetData, "top_cats",
|
||||
new FacetBucket("electronics", NUM_ELECTRONICS),
|
||||
new FacetBucket("currency", NUM_CURRENCY),
|
||||
new FacetBucket("memory", NUM_MEMORY));
|
||||
assertHasFacetWithBucketValues(topLevelFacetData, "top_manufacturers",
|
||||
new FacetBucket("corsair", NUM_CORSAIR),
|
||||
new FacetBucket("belkin", NUM_BELKIN),
|
||||
new FacetBucket("canon", NUM_CANON));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleRangeFacet() throws Exception {
|
||||
final String jsonBody = String.join("\n", "{",
|
||||
" 'query': '*:*',",
|
||||
" 'facet': {",
|
||||
" 'prices': {",
|
||||
" 'type': 'range',",
|
||||
" 'field': 'price',",
|
||||
" 'start': 0,",
|
||||
" 'end': 100,",
|
||||
" 'gap': 20",
|
||||
" }",
|
||||
" }",
|
||||
"}");
|
||||
final DirectJsonQueryRequest request = new DirectJsonQueryRequest(jsonBody);
|
||||
|
||||
QueryResponse response = request.process(getSolrClient(), COLLECTION_NAME);
|
||||
|
||||
assertExpectedDocumentsFoundAndReturned(response, NUM_TECHPRODUCTS_DOCS, 10);
|
||||
final NestableJsonFacet topLevelFacetData = response.getJsonFacetingResponse();
|
||||
assertEquals(NUM_TECHPRODUCTS_DOCS, topLevelFacetData.getCount());
|
||||
assertHasFacetWithBucketValues(topLevelFacetData, "prices",
|
||||
new FacetBucket(0.0f, 5),
|
||||
new FacetBucket(20.0f, 0),
|
||||
new FacetBucket(40.0f, 0),
|
||||
new FacetBucket(60.0f, 1),
|
||||
new FacetBucket(80.0f, 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiRangeFacet() throws Exception {
|
||||
final String jsonBody = String.join("\n", "{",
|
||||
" 'query': '*:*',",
|
||||
" 'facet': {",
|
||||
" 'prices': {",
|
||||
" 'type': 'range',",
|
||||
" 'field': 'price',",
|
||||
" 'start': 0,",
|
||||
" 'end': 100,",
|
||||
" 'gap': 20",
|
||||
" },",
|
||||
" 'shipping_weights': {",
|
||||
" 'type': 'range',",
|
||||
" 'field': 'weight',",
|
||||
" 'start': 0,",
|
||||
" 'end': 200,",
|
||||
" 'gap': 50",
|
||||
" }",
|
||||
" }",
|
||||
"}");
|
||||
final DirectJsonQueryRequest request = new DirectJsonQueryRequest(jsonBody);
|
||||
|
||||
QueryResponse response = request.process(getSolrClient(), COLLECTION_NAME);
|
||||
|
||||
assertExpectedDocumentsFoundAndReturned(response, NUM_TECHPRODUCTS_DOCS, 10);
|
||||
final NestableJsonFacet topLevelFacetData = response.getJsonFacetingResponse();
|
||||
assertEquals(NUM_TECHPRODUCTS_DOCS, topLevelFacetData.getCount());
|
||||
assertHasFacetWithBucketValues(topLevelFacetData, "prices",
|
||||
new FacetBucket(0.0f, 5),
|
||||
new FacetBucket(20.0f, 0),
|
||||
new FacetBucket(40.0f, 0),
|
||||
new FacetBucket(60.0f, 1),
|
||||
new FacetBucket(80.0f, 1));
|
||||
assertHasFacetWithBucketValues(topLevelFacetData, "shipping_weights",
|
||||
new FacetBucket(0.0f, 6),
|
||||
new FacetBucket(50.0f, 0),
|
||||
new FacetBucket(100.0f, 0),
|
||||
new FacetBucket(150.0f, 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleStatFacet() throws Exception {
|
||||
final String jsonBody = String.join("\n", "{",
|
||||
" 'query': '*:*',",
|
||||
" 'facet': {",
|
||||
" 'sum_price': 'sum(price)'",
|
||||
" }",
|
||||
"}");
|
||||
final DirectJsonQueryRequest request = new DirectJsonQueryRequest(jsonBody);
|
||||
|
||||
QueryResponse response = request.process(getSolrClient(), COLLECTION_NAME);
|
||||
|
||||
assertExpectedDocumentsFoundAndReturned(response, NUM_TECHPRODUCTS_DOCS, 10);
|
||||
final NestableJsonFacet topLevelFacetData = response.getJsonFacetingResponse();
|
||||
assertHasStatFacetWithValue(topLevelFacetData, "sum_price", 5251.270030975342);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiStatFacet() throws Exception {
|
||||
final String jsonBody = String.join("\n", "{",
|
||||
" 'query': '*:*',",
|
||||
" 'facet': {",
|
||||
" 'sum_price': 'sum(price)',",
|
||||
" 'avg_price': 'avg(price)'",
|
||||
" }",
|
||||
"}");
|
||||
final DirectJsonQueryRequest request = new DirectJsonQueryRequest(jsonBody);
|
||||
|
||||
QueryResponse response = request.process(getSolrClient(), COLLECTION_NAME);
|
||||
|
||||
assertExpectedDocumentsFoundAndReturned(response, NUM_TECHPRODUCTS_DOCS, 10);
|
||||
final NestableJsonFacet topLevelFacetData = response.getJsonFacetingResponse();
|
||||
assertHasStatFacetWithValue(topLevelFacetData, "sum_price", 5251.270030975342);
|
||||
assertHasStatFacetWithValue(topLevelFacetData, "avg_price", 328.20437693595886);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiFacetsMixedTypes() throws Exception {
|
||||
final String jsonBody = String.join("\n", "{",
|
||||
" 'query': '*:*',",
|
||||
" 'facet': {",
|
||||
" 'avg_price': 'avg(price)',",
|
||||
" 'top_cats': {",
|
||||
" 'type': 'terms',",
|
||||
" 'field': 'cat',",
|
||||
" 'limit': 3",
|
||||
" }",
|
||||
" }",
|
||||
"}");
|
||||
final DirectJsonQueryRequest request = new DirectJsonQueryRequest(jsonBody);
|
||||
|
||||
QueryResponse response = request.process(getSolrClient(), COLLECTION_NAME);
|
||||
|
||||
assertExpectedDocumentsFoundAndReturned(response, NUM_TECHPRODUCTS_DOCS, 10);
|
||||
final NestableJsonFacet topLevelFacetData = response.getJsonFacetingResponse();
|
||||
assertHasStatFacetWithValue(topLevelFacetData, "avg_price", 328.20437693595886);
|
||||
assertHasFacetWithBucketValues(topLevelFacetData, "top_cats",
|
||||
new FacetBucket("electronics", NUM_ELECTRONICS),
|
||||
new FacetBucket("currency", NUM_CURRENCY),
|
||||
new FacetBucket("memory", NUM_MEMORY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNestedTermsFacet() throws Exception {
|
||||
final String subfacetName = "top_manufacturers_for_cat";
|
||||
final String jsonBody = String.join("\n", "{",
|
||||
" 'query': '*:*',",
|
||||
" 'facet': {",
|
||||
" 'top_cats': {",
|
||||
" 'type': 'terms',",
|
||||
" 'field': 'cat',",
|
||||
" 'limit': 3",
|
||||
" 'facet': {",
|
||||
" 'top_manufacturers_for_cat': {",
|
||||
" 'type': 'terms',",
|
||||
" 'field': 'manu_id_s',",
|
||||
" 'limit': 1",
|
||||
" }",
|
||||
" }",
|
||||
" }",
|
||||
" }",
|
||||
"}");
|
||||
final DirectJsonQueryRequest request = new DirectJsonQueryRequest(jsonBody);
|
||||
|
||||
QueryResponse response = request.process(getSolrClient(), COLLECTION_NAME);
|
||||
|
||||
assertExpectedDocumentsFoundAndReturned(response, NUM_TECHPRODUCTS_DOCS, 10);
|
||||
final NestableJsonFacet topLevelFacetData = response.getJsonFacetingResponse();
|
||||
// Test top level facets
|
||||
assertHasFacetWithBucketValues(topLevelFacetData, "top_cats",
|
||||
new FacetBucket("electronics", NUM_ELECTRONICS),
|
||||
new FacetBucket("currency", NUM_CURRENCY),
|
||||
new FacetBucket("memory", NUM_MEMORY));
|
||||
// Test subfacet values for each top-level facet bucket
|
||||
final List<BucketJsonFacet> catBuckets = topLevelFacetData.getBucketBasedFacets("top_cats").getBuckets();
|
||||
assertHasFacetWithBucketValues(catBuckets.get(0), subfacetName, new FacetBucket("corsair", 3));
|
||||
assertHasFacetWithBucketValues(catBuckets.get(1), subfacetName, new FacetBucket("boa", 1));
|
||||
assertHasFacetWithBucketValues(catBuckets.get(2), subfacetName, new FacetBucket("corsair", 3));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNestedFacetsOfMixedTypes() throws Exception {
|
||||
final String subfacetName = "avg_price_for_cat";
|
||||
final String jsonBody = String.join("\n", "{",
|
||||
" 'query': '*:*',",
|
||||
" 'facet': {",
|
||||
" 'top_cats': {",
|
||||
" 'type': 'terms',",
|
||||
" 'field': 'cat',",
|
||||
" 'limit': 3",
|
||||
" 'facet': {",
|
||||
" 'avg_price_for_cat': 'avg(price)'",
|
||||
" }",
|
||||
" }",
|
||||
" }",
|
||||
"}");
|
||||
final DirectJsonQueryRequest request = new DirectJsonQueryRequest(jsonBody);
|
||||
|
||||
QueryResponse response = request.process(getSolrClient(), COLLECTION_NAME);
|
||||
|
||||
assertExpectedDocumentsFoundAndReturned(response, NUM_TECHPRODUCTS_DOCS, 10);
|
||||
final NestableJsonFacet topLevelFacetData = response.getJsonFacetingResponse();
|
||||
// Test top level facets
|
||||
assertHasFacetWithBucketValues(topLevelFacetData, "top_cats",
|
||||
new FacetBucket("electronics", NUM_ELECTRONICS),
|
||||
new FacetBucket("currency", NUM_CURRENCY),
|
||||
new FacetBucket("memory", NUM_MEMORY));
|
||||
// Test subfacet values for each top-level facet bucket
|
||||
final List<BucketJsonFacet> catBuckets = topLevelFacetData.getBucketBasedFacets("top_cats").getBuckets();
|
||||
assertHasStatFacetWithValue(catBuckets.get(0), subfacetName, 252.02909261530095); // electronics
|
||||
assertHasStatFacetWithValue(catBuckets.get(1), subfacetName, 0.0); // currency
|
||||
assertHasStatFacetWithValue(catBuckets.get(2), subfacetName, 129.99499893188477); // memory
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFacetWithDomainFilteredBySimpleQueryString() throws Exception {
|
||||
final String jsonBody = String.join("\n", "{",
|
||||
" 'query': '*:*',",
|
||||
" 'facet': {",
|
||||
" 'top_popular_cats': {",
|
||||
" 'type': 'terms',",
|
||||
" 'field': 'cat',",
|
||||
" 'limit': 3",
|
||||
" 'domain': {",
|
||||
" 'filter': 'popularity:[5 TO 10]'",
|
||||
" }",
|
||||
" }",
|
||||
" }",
|
||||
"}");
|
||||
final DirectJsonQueryRequest request = new DirectJsonQueryRequest(jsonBody);
|
||||
|
||||
QueryResponse response = request.process(getSolrClient(), COLLECTION_NAME);
|
||||
|
||||
assertExpectedDocumentsFoundAndReturned(response, NUM_TECHPRODUCTS_DOCS, 10);
|
||||
final NestableJsonFacet topLevelFacetData = response.getJsonFacetingResponse();
|
||||
assertHasFacetWithBucketValues(topLevelFacetData, "top_popular_cats",
|
||||
new FacetBucket("electronics", 9),
|
||||
new FacetBucket("graphics card", 2),
|
||||
new FacetBucket("hard drive", 2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFacetWithDomainFilteredByLocalParamsQueryString() throws Exception {
|
||||
final String jsonBody = String.join("\n", "{",
|
||||
" 'query': '*:*',",
|
||||
" 'facet': {",
|
||||
" 'top_popular_cats': {",
|
||||
" 'type': 'terms',",
|
||||
" 'field': 'cat',",
|
||||
" 'limit': 3",
|
||||
" 'domain': {",
|
||||
" 'filter': '{!lucene df=\"popularity\" v=\"[5 TO 10]\"}'",
|
||||
" }",
|
||||
" }",
|
||||
" }",
|
||||
"}");
|
||||
final DirectJsonQueryRequest request = new DirectJsonQueryRequest(jsonBody);
|
||||
QueryResponse response = request.process(getSolrClient(), COLLECTION_NAME);
|
||||
|
||||
assertExpectedDocumentsFoundAndReturned(response, NUM_TECHPRODUCTS_DOCS, 10);
|
||||
final NestableJsonFacet topLevelFacetData = response.getJsonFacetingResponse();
|
||||
assertHasFacetWithBucketValues(topLevelFacetData, "top_popular_cats",
|
||||
new FacetBucket("electronics", 9),
|
||||
new FacetBucket("graphics card", 2),
|
||||
new FacetBucket("hard drive", 2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFacetWithArbitraryDomainFromQueryString() throws Exception {
|
||||
final String jsonBody = String.join("\n", "{",
|
||||
" 'query': 'cat:electronics',",
|
||||
" 'facet': {",
|
||||
" 'top_cats': {",
|
||||
" 'type': 'terms',",
|
||||
" 'field': 'cat',",
|
||||
" 'limit': 3",
|
||||
" 'domain': {",
|
||||
" 'query': '*:*'",
|
||||
" }",
|
||||
" }",
|
||||
" }",
|
||||
"}");
|
||||
final DirectJsonQueryRequest request = new DirectJsonQueryRequest(jsonBody);
|
||||
|
||||
QueryResponse response = request.process(getSolrClient(), COLLECTION_NAME);
|
||||
|
||||
assertExpectedDocumentsFoundAndReturned(response, NUM_ELECTRONICS, 10);
|
||||
final NestableJsonFacet topLevelFacetData = response.getJsonFacetingResponse();
|
||||
assertHasFacetWithBucketValues(topLevelFacetData, "top_cats",
|
||||
new FacetBucket("electronics", NUM_ELECTRONICS),
|
||||
new FacetBucket("currency", NUM_CURRENCY),
|
||||
new FacetBucket("memory", NUM_MEMORY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFacetWithArbitraryDomainFromLocalParamsQuery() throws Exception {
|
||||
final String jsonBody = String.join("\n", "{",
|
||||
" 'query': 'cat:electronics',",
|
||||
" 'facet': {",
|
||||
" 'largest_search_cats': {",
|
||||
" 'type': 'terms',",
|
||||
" 'field': 'cat',",
|
||||
" 'domain': {",
|
||||
" 'query': '{!lucene df=\"cat\" v=\"search\"}'",
|
||||
" }",
|
||||
" }",
|
||||
" }",
|
||||
"}");
|
||||
final DirectJsonQueryRequest request = new DirectJsonQueryRequest(jsonBody);
|
||||
|
||||
QueryResponse response = request.process(getSolrClient(), COLLECTION_NAME);
|
||||
|
||||
assertExpectedDocumentsFoundAndReturned(response, NUM_ELECTRONICS, 10);
|
||||
final NestableJsonFacet topLevelFacetData = response.getJsonFacetingResponse();
|
||||
assertHasFacetWithBucketValues(topLevelFacetData, "largest_search_cats",
|
||||
new FacetBucket("search", 2),
|
||||
new FacetBucket("software", 2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFacetWithMultipleSimpleQueryClausesInArbitraryDomain() throws Exception {
|
||||
final String jsonBody = String.join("\n", "{",
|
||||
" 'query': 'cat:electronics',",
|
||||
" 'facet': {",
|
||||
" 'cats_matching_solr': {",
|
||||
" 'type': 'terms',",
|
||||
" 'field': 'cat',",
|
||||
" 'domain': {",
|
||||
" 'query': ['cat:search', 'name:Solr']",
|
||||
" }",
|
||||
" }",
|
||||
" }",
|
||||
"}");
|
||||
final DirectJsonQueryRequest request = new DirectJsonQueryRequest(jsonBody);
|
||||
|
||||
QueryResponse response = request.process(getSolrClient(), COLLECTION_NAME);
|
||||
|
||||
assertExpectedDocumentsFoundAndReturned(response, NUM_ELECTRONICS, 10);
|
||||
final NestableJsonFacet topLevelFacetData = response.getJsonFacetingResponse();
|
||||
assertHasFacetWithBucketValues(topLevelFacetData, "cats_matching_solr",
|
||||
new FacetBucket("search", 1),
|
||||
new FacetBucket("software", 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFacetWithMultipleLocalParamsQueryClausesInArbitraryDomain() throws Exception {
|
||||
final String jsonBody = String.join("\n", "{",
|
||||
" 'query': 'cat:electronics',",
|
||||
" 'facet': {",
|
||||
" 'cats_matching_solr': {",
|
||||
" 'type': 'terms',",
|
||||
" 'field': 'cat',",
|
||||
" 'domain': {",
|
||||
" 'query': ['{!lucene df=\"cat\" v=\"search\"}', '{!lucene df=\"name\" v=\"Solr\"}']",
|
||||
" }",
|
||||
" }",
|
||||
" }",
|
||||
"}");
|
||||
final DirectJsonQueryRequest request = new DirectJsonQueryRequest(jsonBody);
|
||||
|
||||
QueryResponse response = request.process(getSolrClient(), COLLECTION_NAME);
|
||||
|
||||
assertExpectedDocumentsFoundAndReturned(response, NUM_ELECTRONICS, 10);
|
||||
final NestableJsonFacet topLevelFacetData = response.getJsonFacetingResponse();
|
||||
assertHasFacetWithBucketValues(topLevelFacetData, "cats_matching_solr",
|
||||
new FacetBucket("search", 1),
|
||||
new FacetBucket("software", 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFacetWithDomainWidenedUsingExcludeTagsToIgnoreFilters() throws Exception {
|
||||
final String jsonBody = String.join("\n", "{",
|
||||
" 'query': '*:*',",
|
||||
" 'filter': {'#on_shelf': 'inStock:true'},",
|
||||
" 'facet': {",
|
||||
" 'in_stock_only': {",
|
||||
" 'type': 'terms',",
|
||||
" 'field': 'cat',",
|
||||
" 'limit': 2",
|
||||
" }",
|
||||
" 'all': {",
|
||||
" 'type': 'terms',",
|
||||
" 'field': 'cat',",
|
||||
" 'limit': 2,",
|
||||
" 'domain': {",
|
||||
" 'excludeTags': 'on_shelf'",
|
||||
" }",
|
||||
" }",
|
||||
" }",
|
||||
"}");
|
||||
final DirectJsonQueryRequest request = new DirectJsonQueryRequest(jsonBody);
|
||||
|
||||
QueryResponse response = request.process(getSolrClient(), COLLECTION_NAME);
|
||||
|
||||
assertExpectedDocumentsFoundAndReturned(response, NUM_IN_STOCK, 10);
|
||||
final NestableJsonFacet topLevelFacetData = response.getJsonFacetingResponse();
|
||||
assertHasFacetWithBucketValues(topLevelFacetData, "in_stock_only",
|
||||
new FacetBucket("electronics", 8),
|
||||
new FacetBucket("currency", 4));
|
||||
assertHasFacetWithBucketValues(topLevelFacetData, "all",
|
||||
new FacetBucket("electronics", 12),
|
||||
new FacetBucket("currency", 4));
|
||||
}
|
||||
|
||||
private class FacetBucket {
|
||||
private final Object val;
|
||||
private final int count;
|
||||
|
||||
FacetBucket(Object val, int count) {
|
||||
this.val = val;
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
public Object getVal() {
|
||||
return val;
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
private void assertHasFacetWithBucketValues(NestableJsonFacet response, String expectedFacetName,
|
||||
FacetBucket... expectedBuckets) {
|
||||
assertTrue("Expected response to have facet with name " + expectedFacetName,
|
||||
response.getBucketBasedFacets(expectedFacetName) != null);
|
||||
final List<BucketJsonFacet> buckets = response.getBucketBasedFacets(expectedFacetName).getBuckets();
|
||||
assertEquals(expectedBuckets.length, buckets.size());
|
||||
for (int i = 0; i < expectedBuckets.length; i++) {
|
||||
final FacetBucket expectedBucket = expectedBuckets[i];
|
||||
final BucketJsonFacet actualBucket = buckets.get(i);
|
||||
assertEquals(expectedBucket.getVal(), actualBucket.getVal());
|
||||
assertEquals(expectedBucket.getCount(), actualBucket.getCount());
|
||||
}
|
||||
}
|
||||
|
||||
private void assertHasStatFacetWithValue(NestableJsonFacet response, String expectedFacetName,
|
||||
Double expectedStatValue) {
|
||||
assertTrue("Expected response to have stat facet named '" + expectedFacetName + "'",
|
||||
response.getStatValue(expectedFacetName) != null);
|
||||
assertEquals(expectedStatValue, response.getStatValue(expectedFacetName));
|
||||
}
|
||||
|
||||
private void assertExpectedDocumentsFoundAndReturned(QueryResponse response, int expectedNumFound,
|
||||
int expectedReturned) {
|
||||
assertEquals(0, response.getStatus());
|
||||
final SolrDocumentList documents = response.getResults();
|
||||
assertEquals(expectedNumFound, documents.getNumFound());
|
||||
assertEquals(expectedReturned, documents.size());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue