/*
* 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;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexableField;
import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.SolrInputField;
import org.apache.solr.core.SolrCore;
import org.apache.solr.schema.FieldType;
import org.apache.solr.schema.IndexSchema;
import org.junit.BeforeClass;
import org.junit.Test;
/**
*
*
*/
public class DocumentBuilderTest extends SolrTestCaseJ4 {
@BeforeClass
public static void beforeClass() throws Exception {
initCore("solrconfig.xml", "schema.xml");
}
@Test
public void testBuildDocument() throws Exception
{
SolrCore core = h.getCore();
// undefined field
try {
SolrInputDocument doc = new SolrInputDocument();
doc.setField( "unknown field", 12345, 1.0f );
DocumentBuilder.toDocument( doc, core.getSchema() );
fail( "should throw an error" );
}
catch( SolrException ex ) {
assertEquals( "should be bad request", 400, ex.code() );
}
}
@Test
public void testNullField()
{
SolrCore core = h.getCore();
// make sure a null value is not indexed
SolrInputDocument doc = new SolrInputDocument();
doc.addField( "name", null, 1.0f );
Document out = DocumentBuilder.toDocument( doc, core.getSchema() );
assertNull( out.get( "name" ) );
}
@Test
public void testExceptions()
{
SolrCore core = h.getCore();
// make sure a null value is not indexed
SolrInputDocument doc = new SolrInputDocument();
doc.addField( "id", "123", 1.0f );
doc.addField( "unknown", "something", 1.0f );
try {
DocumentBuilder.toDocument( doc, core.getSchema() );
fail( "added an unknown field" );
}
catch( Exception ex ) {
assertTrue( "should have document ID", ex.getMessage().indexOf( "doc=123" ) > 0 );
}
doc.remove( "unknown" );
doc.addField( "weight", "not a number", 1.0f );
try {
DocumentBuilder.toDocument( doc, core.getSchema() );
fail( "invalid 'float' field value" );
}
catch( Exception ex ) {
assertTrue( "should have document ID", ex.getMessage().indexOf( "doc=123" ) > 0 );
assertTrue( "cause is number format", ex.getCause() instanceof NumberFormatException );
}
// now make sure it is OK
doc.setField( "weight", "1.34", 1.0f );
DocumentBuilder.toDocument( doc, core.getSchema() );
}
@Test
public void testMultiField() throws Exception {
SolrCore core = h.getCore();
// make sure a null value is not indexed
SolrInputDocument doc = new SolrInputDocument();
doc.addField( "home", "2.2,3.3", 1.0f );
Document out = DocumentBuilder.toDocument( doc, core.getSchema() );
assertNotNull( out.get( "home" ) );//contains the stored value and term vector, if there is one
assertNotNull( out.getField( "home_0" + FieldType.POLY_FIELD_SEPARATOR + "double" ) );
assertNotNull( out.getField( "home_1" + FieldType.POLY_FIELD_SEPARATOR + "double" ) );
}
@Test
public void testCopyFieldWithDocumentBoost() {
SolrCore core = h.getCore();
IndexSchema schema = core.getSchema();
assertFalse(schema.getField("title").omitNorms());
assertTrue(schema.getField("title_stringNoNorms").omitNorms());
SolrInputDocument doc = new SolrInputDocument();
doc.setDocumentBoost(3f);
doc.addField( "title", "mytitle");
Document out = DocumentBuilder.toDocument( doc, core.getSchema() );
assertNotNull( out.get( "title_stringNoNorms" ) );
assertTrue("title_stringNoNorms has the omitNorms attribute set to true, if the boost is different than 1.0, it will fail",1.0f == out.getField( "title_stringNoNorms" ).boost() );
assertTrue("It is OK that title has a boost of 3",3.0f == out.getField( "title" ).boost() );
}
@Test
public void testCopyFieldWithFieldBoost() {
SolrCore core = h.getCore();
IndexSchema schema = core.getSchema();
assertFalse(schema.getField("title").omitNorms());
assertTrue(schema.getField("title_stringNoNorms").omitNorms());
SolrInputDocument doc = new SolrInputDocument();
doc.addField( "title", "mytitle", 3.0f );
Document out = DocumentBuilder.toDocument( doc, core.getSchema() );
assertNotNull( out.get( "title_stringNoNorms" ) );
assertTrue("title_stringNoNorms has the omitNorms attribute set to true, if the boost is different than 1.0, it will fail",1.0f == out.getField( "title_stringNoNorms" ).boost() );
assertTrue("It is OK that title has a boost of 3",3.0f == out.getField( "title" ).boost() );
}
@Test
public void testWithPolyFieldsAndFieldBoost() {
SolrCore core = h.getCore();
IndexSchema schema = core.getSchema();
assertFalse(schema.getField("store").omitNorms());
assertTrue(schema.getField("store_0_coordinate").omitNorms());
assertTrue(schema.getField("store_1_coordinate").omitNorms());
assertFalse(schema.getField("amount").omitNorms());
assertTrue(schema.getField("amount" + FieldType.POLY_FIELD_SEPARATOR + "_currency").omitNorms());
assertTrue(schema.getField("amount" + FieldType.POLY_FIELD_SEPARATOR + "_amount_raw").omitNorms());
SolrInputDocument doc = new SolrInputDocument();
doc.addField( "store", "40.7143,-74.006", 3.0f );
doc.addField( "amount", "10.5", 3.0f );
Document out = DocumentBuilder.toDocument( doc, core.getSchema() );
assertNotNull( out.get( "store" ) );
assertNotNull( out.get( "amount" ) );
assertNotNull(out.getField("store_0_coordinate"));
//NOTE: As the subtypes have omitNorm=true, they must have boost=1F, otherwise this is going to fail when adding the doc to Lucene.
assertTrue(1f == out.getField("store_0_coordinate").boost());
assertTrue(1f == out.getField("store_1_coordinate").boost());
assertTrue(1f == out.getField("amount" + FieldType.POLY_FIELD_SEPARATOR + "_currency").boost());
assertTrue(1f == out.getField("amount" + FieldType.POLY_FIELD_SEPARATOR + "_amount_raw").boost());
}
@Test
public void testWithPolyFieldsAndDocumentBoost() {
SolrCore core = h.getCore();
IndexSchema schema = core.getSchema();
assertFalse(schema.getField("store").omitNorms());
assertTrue(schema.getField("store_0_coordinate").omitNorms());
assertTrue(schema.getField("store_1_coordinate").omitNorms());
assertFalse(schema.getField("amount").omitNorms());
assertTrue(schema.getField("amount" + FieldType.POLY_FIELD_SEPARATOR + "_currency").omitNorms());
assertTrue(schema.getField("amount" + FieldType.POLY_FIELD_SEPARATOR + "_amount_raw").omitNorms());
SolrInputDocument doc = new SolrInputDocument();
doc.setDocumentBoost(3.0f);
doc.addField( "store", "40.7143,-74.006");
doc.addField( "amount", "10.5");
Document out = DocumentBuilder.toDocument( doc, core.getSchema() );
assertNotNull( out.get( "store" ) );
assertNotNull(out.getField("store_0_coordinate"));
//NOTE: As the subtypes have omitNorm=true, they must have boost=1F, otherwise this is going to fail when adding the doc to Lucene.
assertTrue(1f == out.getField("store_0_coordinate").boost());
assertTrue(1f == out.getField("store_1_coordinate").boost());
assertTrue(1f == out.getField("amount" + FieldType.POLY_FIELD_SEPARATOR + "_currency").boost());
assertTrue(1f == out.getField("amount" + FieldType.POLY_FIELD_SEPARATOR + "_amount_raw").boost());
}
/**
* Its ok to boost a field if it has norms
*/
public void testBoost() throws Exception {
XmlDoc xml = new XmlDoc();
xml.xml = "<doc>"
+ "<field name=\"id\">0</field>"
+ "<field name=\"title\" boost=\"3.0\">mytitle</field>"
+ "</doc>";
assertNull(h.validateUpdate(add(xml, new String[0])));
}
public void testMultiValuedFielAndDocBoosts() throws Exception {
SolrCore core = h.getCore();
IndexSchema schema = core.getSchema();
SolrInputDocument doc = new SolrInputDocument();
doc.setDocumentBoost(3.0f);
SolrInputField field = new SolrInputField( "foo_t" );
field.addValue( "summer time" , 1.0f );
field.addValue( "in the city" , 5.0f ); // using boost
field.addValue( "living is easy" , 1.0f );
doc.put( field.getName(), field );
Document out = DocumentBuilder.toDocument( doc, core.getSchema() );
IndexableField[] outF = out.getFields( field.getName() );
assertEquals("wrong number of field values",
3, outF.length);
// since Lucene no longer has native documnt boosts, we should find
// the doc boost multiplied into the boost o nthe first field value
// all other field values should be 1.0f
// (lucene will multiply all of the field boosts later)
assertEquals(15.0f, outF[0].boost(), 0.0f);
assertEquals(1.0f, outF[1].boost(), 0.0f);
assertEquals(1.0f, outF[2].boost(), 0.0f);
}
/**
* Its not ok to boost a field if it omits norms
*/
public void testBoostOmitNorms() throws Exception {
XmlDoc xml = new XmlDoc();
xml.xml = "<doc>"
+ "<field name=\"id\">ignore_exception</field>"
+ "<field name=\"title_stringNoNorms\" boost=\"3.0\">mytitle</field>"
+ "</doc>";
try {
assertNull(h.validateUpdate(add(xml, new String[0])));
fail("didn't get expected exception for boosting omit norms field");
} catch (SolrException expected) {
// expected exception
}
}
/**
* Its ok to supply a document boost even if a field omits norms
*/
public void testDocumentBoostOmitNorms() throws Exception {
XmlDoc xml = new XmlDoc();
xml.xml = "<doc boost=\"3.0\">"
+ "<field name=\"id\">2</field>"
+ "<field name=\"title_stringNoNorms\">mytitle</field>"
+ "</doc>";
assertNull(h.validateUpdate(add(xml, new String[0])));
}
}