blob: 3763af15db1a551dacbbf8fbe1e1a8d40112db1a [file] [log] [blame]
/*
* 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.schema;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import javax.xml.xpath.XPathConstants;
import org.apache.lucene.index.LeafReader;
import org.apache.lucene.util.BytesRef;
import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.util.ErrorLogMuter;
import org.apache.solr.util.TestHarness;
import org.junit.BeforeClass;
import org.junit.Ignore;
public class RankFieldTest extends SolrTestCaseJ4 {
private static final String RANK_1 = "rank_1";
private static final String RANK_2 = "rank_2";
@BeforeClass
public static void beforeClass() throws Exception {
initCore("solrconfig-minimal.xml","schema-rank-fields.xml");
}
@Override
public void setUp() throws Exception {
clearIndex();
assertU(commit());
super.setUp();
}
public void testInternalFieldName() {
assertEquals("RankField.INTERNAL_RANK_FIELD_NAME changed in an incompatible way",
"_rank_", RankField.INTERNAL_RANK_FIELD_NAME);
}
public void testBasic() {
assertNotNull(h.getCore().getLatestSchema().getFieldOrNull(RANK_1));
assertEquals(RankField.class, h.getCore().getLatestSchema().getField(RANK_1).getType().getClass());
}
public void testBadFormat() {
try (ErrorLogMuter errors = ErrorLogMuter.substring("Expecting float")) {
assertFailedU(adoc(
"id", "1",
RANK_1, "foo"
));
assertFailedU(adoc(
"id", "1",
RANK_1, "1.2.3"
));
assertEquals(2, errors.getCount());
}
try (ErrorLogMuter errors = ErrorLogMuter.substring("must be finite")) {
assertFailedU(adoc(
"id", "1",
RANK_1, Float.toString(Float.POSITIVE_INFINITY)
));
assertFailedU(adoc(
"id", "1",
RANK_1, Float.toString(Float.NEGATIVE_INFINITY)
));
assertFailedU(adoc(
"id", "1",
RANK_1, Float.toString(Float.NaN)
));
assertEquals(3, errors.getCount());
}
try (ErrorLogMuter errors = ErrorLogMuter.substring("must be a positive")) {
assertFailedU(adoc(
"id", "1",
RANK_1, Float.toString(-0.0f)
));
assertFailedU(adoc(
"id", "1",
RANK_1, Float.toString(-1f)
));
assertFailedU(adoc(
"id", "1",
RANK_1, Float.toString(0.0f)
));
assertEquals(3, errors.getCount());
}
}
public void testAddRandom() {
for (int i = 0 ; i < random().nextInt(TEST_NIGHTLY ? 10000 : 100); i++) {
assertU(adoc(
"id", String.valueOf(i),
RANK_1, Float.toString(random().nextFloat())
));
}
assertU(commit());
}
public void testSkipEmpty() {
assertU(adoc(
"id", "1",
RANK_1, ""
));
}
public void testBasicAdd() throws IOException {
assertU(adoc(
"id", "testBasicAdd",
RANK_1, "1"
));
assertU(commit());
//assert that the document made it in
assertQ(req("q", "id:testBasicAdd"), "//*[@numFound='1']");
h.getCore().withSearcher((searcher) -> {
LeafReader reader = searcher.getIndexReader().getContext().leaves().get(0).reader();
// assert that the field made it in
assertNotNull(reader.getFieldInfos().fieldInfo(RankField.INTERNAL_RANK_FIELD_NAME));
// assert that the feature made it in
assertTrue(reader.terms(RankField.INTERNAL_RANK_FIELD_NAME).iterator().seekExact(new BytesRef(RANK_1.getBytes(StandardCharsets.UTF_8))));
return null;
});
}
public void testMultipleRankFields() throws IOException {
assertU(adoc(
"id", "testMultiValueAdd",
RANK_1, "1",
RANK_2, "2"
));
assertU(commit());
//assert that the document made it in
assertQ(req("q", "id:testMultiValueAdd"), "//*[@numFound='1']");
h.getCore().withSearcher((searcher) -> {
LeafReader reader = searcher.getIndexReader().getContext().leaves().get(0).reader();
// assert that the field made it in
assertNotNull(reader.getFieldInfos().fieldInfo(RankField.INTERNAL_RANK_FIELD_NAME));
// assert that the features made it in
assertTrue(reader.terms(RankField.INTERNAL_RANK_FIELD_NAME).iterator().seekExact(new BytesRef(RANK_2.getBytes(StandardCharsets.UTF_8))));
assertTrue(reader.terms(RankField.INTERNAL_RANK_FIELD_NAME).iterator().seekExact(new BytesRef(RANK_1.getBytes(StandardCharsets.UTF_8))));
return null;
});
}
public void testSortFails() throws IOException {
assertU(adoc(
"id", "testSortFails",
RANK_1, "1"
));
assertU(commit());
assertQEx("Can't sort on rank field", req(
"q", "id:testSortFails",
"sort", RANK_1 + " desc"), 400);
}
@Ignore("We currently don't fail these kinds of requests with other field types")
public void testFacetFails() throws IOException {
assertU(adoc(
"id", "testFacetFails",
RANK_1, "1"
));
assertU(commit());
assertQEx("Can't facet on rank field", req(
"q", "id:testFacetFails",
"facet", "true",
"facet.field", RANK_1), 400);
}
public void testTermQuery() throws IOException {
assertU(adoc(
"id", "testTermQuery",
RANK_1, "1",
RANK_2, "1"
));
assertU(adoc(
"id", "testTermQuery2",
RANK_1, "1"
));
assertU(commit());
assertQ(req("q", RANK_1 + ":*"), "//*[@numFound='2']");
assertQ(req("q", RANK_1 + ":[* TO *]"), "//*[@numFound='2']");
assertQ(req("q", RANK_2 + ":*"), "//*[@numFound='1']");
assertQ(req("q", RANK_2 + ":[* TO *]"), "//*[@numFound='1']");
assertQEx("Term queries not supported", req("q", RANK_1 + ":1"), 400);
assertQEx("Range queries not supported", req("q", RANK_1 + ":[1 TO 10]"), 400);
}
public void testResponseQuery() throws IOException {
assertU(adoc(
"id", "testResponseQuery",
RANK_1, "1"
));
assertU(commit());
// Ignore requests to retrieve rank
assertQ(req("q", RANK_1 + ":*",
"fl", "id," + RANK_1),
"//*[@numFound='1']",
"count(//result/doc[1]/str)=1");
}
public void testRankQParserQuery() throws IOException {
assertU(adoc(
"id", "1",
"str_field", "foo",
RANK_1, "1",
RANK_2, "2"
));
assertU(adoc(
"id", "2",
"str_field", "foo",
RANK_1, "2",
RANK_2, "1"
));
assertU(commit());
assertQ(req("q", "str_field:foo _query_:{!rank f='" + RANK_1 + "' function='log' scalingFactor='1'}"),
"//*[@numFound='2']",
"//result/doc[1]/str[@name='id'][.='2']",
"//result/doc[2]/str[@name='id'][.='1']");
assertQ(req("q", "str_field:foo _query_:{!rank f='" + RANK_2 + "' function='log' scalingFactor='1'}"),
"//*[@numFound='2']",
"//result/doc[1]/str[@name='id'][.='1']",
"//result/doc[2]/str[@name='id'][.='2']");
assertQ(req("q", "foo",
"defType", "dismax",
"qf", "str_field^10",
"bq", "{!rank f='" + RANK_1 + "' function='log' scalingFactor='1'}"
),
"//*[@numFound='2']",
"//result/doc[1]/str[@name='id'][.='2']",
"//result/doc[2]/str[@name='id'][.='1']");
assertQ(req("q", "foo",
"defType", "dismax",
"qf", "str_field^10",
"bq", "{!rank f='" + RANK_2 + "' function='log' scalingFactor='1'}"
),
"//*[@numFound='2']",
"//result/doc[1]/str[@name='id'][.='1']",
"//result/doc[2]/str[@name='id'][.='2']");
}
public void testScoreChanges() throws Exception {
assertU(adoc(
"id", "1",
"str_field", "foo",
RANK_1, "1"
));
assertU(commit());
ModifiableSolrParams params = params("q", "foo",
"defType", "dismax",
"qf", "str_field^10",
"fl", "id,score",
"wt", "xml");
double scoreBefore = (Double) TestHarness.evaluateXPath(h.query(req(params)), "//result/doc[1]/float[@name='score']", XPathConstants.NUMBER);
params.add("bq", "{!rank f='" + RANK_1 + "' function='log' scalingFactor='1'}");
double scoreAfter = (Double) TestHarness.evaluateXPath(h.query(req(params)), "//result/doc[1]/float[@name='score']", XPathConstants.NUMBER);
assertNotEquals("Expecting score to change", scoreBefore, scoreAfter, 0f);
}
}