blob: cc917765f156d4f23045343226f7344d74c7fb58 [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.handler;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.UnaryOperator;
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.common.util.ContentStreamBase;
import org.apache.solr.common.util.Utils;
import org.apache.solr.handler.loader.JsonLoader;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.update.AddUpdateCommand;
import org.apache.solr.update.CommitUpdateCommand;
import org.apache.solr.update.DeleteUpdateCommand;
import org.apache.solr.update.processor.BufferingRequestProcessor;
import org.junit.BeforeClass;
import org.junit.Test;
public class JsonLoaderTest extends SolrTestCaseJ4 {
@BeforeClass
public static void beforeTests() throws Exception {
initCore("solrconfig.xml","schema.xml");
}
static String input = json("{\n" +
"\n" +
"'add': {\n" +
" 'doc': {\n" +
" 'bool': true,\n" +
" 'f0': 'v0',\n" +
" 'array': [ 'aaa', 'bbb' ]\n" +
" }\n" +
"},\n" +
"'add': {\n" +
" 'commitWithin': 1234,\n" +
" 'overwrite': false,\n" +
" 'boost': 3.45,\n" +
" 'doc': {\n" +
" 'f1': 'v1',\n" +
" 'f1': 'v2',\n" +
" 'f2': null\n" +
" }\n" +
"},\n" +
"\n" +
"'commit': {},\n" +
"'optimize': { 'waitSearcher':false, 'openSearcher':false },\n" +
"\n" +
"'delete': { 'id':'ID' },\n" +
"'delete': { 'id':'ID', 'commitWithin':500 },\n" +
"'delete': { 'query':'QUERY' },\n" +
"'delete': { 'query':'QUERY', 'commitWithin':500 },\n" +
"'rollback': {}\n" +
"\n" +
"}\n" +
"");
public void testParsing() throws Exception
{
SolrQueryRequest req = req();
SolrQueryResponse rsp = new SolrQueryResponse();
BufferingRequestProcessor p = new BufferingRequestProcessor(null);
JsonLoader loader = new JsonLoader();
loader.load(req, rsp, new ContentStreamBase.StringStream(input), p);
assertEquals( 2, p.addCommands.size() );
AddUpdateCommand add = p.addCommands.get(0);
assertEquals("SolrInputDocument(fields: [bool=true, f0=v0, array=[aaa, bbb]])", add.solrDoc.toString());
//
add = p.addCommands.get(1);
assertEquals("SolrInputDocument(fields: [f1=[v1, v2], f2=null])", add.solrDoc.toString());
assertFalse(add.overwrite);
// parse the commit commands
assertEquals( 2, p.commitCommands.size() );
CommitUpdateCommand commit = p.commitCommands.get( 0 );
assertFalse( commit.optimize );
assertTrue( commit.waitSearcher );
assertTrue( commit.openSearcher );
commit = p.commitCommands.get( 1 );
assertTrue( commit.optimize );
assertFalse( commit.waitSearcher );
assertFalse( commit.openSearcher );
// DELETE COMMANDS
assertEquals( 4, p.deleteCommands.size() );
DeleteUpdateCommand delete = p.deleteCommands.get( 0 );
assertEquals( delete.id, "ID" );
assertNull( delete.query );
assertEquals( delete.commitWithin, -1);
delete = p.deleteCommands.get( 1 );
assertEquals( delete.id, "ID" );
assertNull( delete.query );
assertEquals( delete.commitWithin, 500);
delete = p.deleteCommands.get( 2 );
assertNull( delete.id );
assertEquals( delete.query, "QUERY" );
assertEquals( delete.commitWithin, -1);
delete = p.deleteCommands.get( 3 );
assertNull( delete.id );
assertEquals( delete.query, "QUERY" );
assertEquals( delete.commitWithin, 500);
// ROLLBACK COMMANDS
assertEquals( 1, p.rollbackCommands.size() );
req.close();
}
public void testSimpleFormat() throws Exception
{
String str = "[{'id':'1'},{'id':'2'}]".replace('\'', '"');
SolrQueryRequest req = req("commitWithin","100", "overwrite","false");
SolrQueryResponse rsp = new SolrQueryResponse();
BufferingRequestProcessor p = new BufferingRequestProcessor(null);
JsonLoader loader = new JsonLoader();
loader.load(req, rsp, new ContentStreamBase.StringStream(str), p);
assertEquals( 2, p.addCommands.size() );
AddUpdateCommand add = p.addCommands.get(0);
SolrInputDocument d = add.solrDoc;
SolrInputField f = d.getField( "id" );
assertEquals("1", f.getValue());
assertEquals(add.commitWithin, 100);
assertFalse(add.overwrite);
add = p.addCommands.get(1);
d = add.solrDoc;
f = d.getField( "id" );
assertEquals("2", f.getValue());
assertEquals(add.commitWithin, 100);
assertFalse(add.overwrite);
req.close();
}
@Test
public void testInvalidJsonProducesBadRequestSolrException() throws Exception {
SolrQueryResponse rsp = new SolrQueryResponse();
BufferingRequestProcessor p = new BufferingRequestProcessor(null);
JsonLoader loader = new JsonLoader();
String invalidJsonString = "}{";
SolrException ex = expectThrows(SolrException.class, () -> {
loader.load(req(), rsp, new ContentStreamBase.StringStream(invalidJsonString), p);
});
assertEquals(SolrException.ErrorCode.BAD_REQUEST.code, ex.code());
assertTrue(ex.getMessage().contains("Cannot parse"));
assertTrue(ex.getMessage().contains("JSON"));
}
public void testSimpleFormatInAdd() throws Exception
{
String str = "{'add':[{'id':'1'},{'id':'2'}]}".replace('\'', '"');
SolrQueryRequest req = req();
SolrQueryResponse rsp = new SolrQueryResponse();
BufferingRequestProcessor p = new BufferingRequestProcessor(null);
JsonLoader loader = new JsonLoader();
loader.load(req, rsp, new ContentStreamBase.StringStream(str), p);
assertEquals( 2, p.addCommands.size() );
AddUpdateCommand add = p.addCommands.get(0);
SolrInputDocument d = add.solrDoc;
SolrInputField f = d.getField( "id" );
assertEquals("1", f.getValue());
assertEquals(add.commitWithin, -1);
assertTrue(add.overwrite);
add = p.addCommands.get(1);
d = add.solrDoc;
f = d.getField( "id" );
assertEquals("2", f.getValue());
assertEquals(add.commitWithin, -1);
assertTrue(add.overwrite);
req.close();
}
public void testFieldValueOrdering() throws Exception {
final String pre = "{'add':[{'id':'1',";
final String post = "},{'id':'2'}]}";
// list
checkFieldValueOrdering((pre+ "'f':[45,67,89]" +post)
.replace('\'', '"')
);
// dup fieldname keys
checkFieldValueOrdering((pre+ "'f':45,'f':67,'f':89" +post)
.replace('\'', '"')
);
}
private void checkFieldValueOrdering(String rawJson) throws Exception {
SolrQueryRequest req = req();
SolrQueryResponse rsp = new SolrQueryResponse();
BufferingRequestProcessor p = new BufferingRequestProcessor(null);
JsonLoader loader = new JsonLoader();
loader.load(req, rsp, new ContentStreamBase.StringStream(rawJson), p);
assertEquals( 2, p.addCommands.size() );
SolrInputDocument d = p.addCommands.get(0).solrDoc;
assertEquals(2, d.getFieldNames().size());
assertEquals("1", d.getFieldValue("id"));
assertArrayEquals(new Object[] {45L, 67L, 89L} , d.getFieldValues("f").toArray());
d = p.addCommands.get(1).solrDoc;
assertEquals(1, d.getFieldNames().size());
assertEquals("2", d.getFieldValue("id"));
req.close();
}
public void testMultipleDocsWithoutArray() throws Exception {
String doc = "\n" +
"\n" +
"{\"f1\": 1111 }\n" +
"\n" +
"{\"f1\": 2222 }\n";
SolrQueryRequest req = req("srcField","_src_");
req.getContext().put("path","/update/json/docs");
SolrQueryResponse rsp = new SolrQueryResponse();
BufferingRequestProcessor p = new BufferingRequestProcessor(null);
JsonLoader loader = new JsonLoader();
loader.load(req, rsp, new ContentStreamBase.StringStream(doc), p);
assertEquals( 2, p.addCommands.size() );
}
public void testJsonDocFormat() throws Exception{
String doc;
SolrQueryRequest req;
SolrQueryResponse rsp;
BufferingRequestProcessor p;
JsonLoader loader;
doc = "\n" +
"\n" +
"{\"bool\": true,\n" +
" \"f0\": \"v0\",\n" +
" \"f2\": {\n" +
" \t \"boost\": 2.3,\n" +
" \t \"value\": \"test\"\n" +
" \t },\n" +
"\"array\": [ \"aaa\", \"bbb\" ],\n" +
"\"boosted\": {\n" +
" \t \"boost\": 6.7,\n" +
" \t \"value\": [ \"aaa\", \"bbb\" ]\n" +
" \t }\n" +
" }\n" +
"\n" +
"\n" +
" {\"f1\": \"v1\",\n" +
" \"f2\": \"v2\",\n" +
" \"f3\": null\n" +
" }\n";
req = req("srcField","_src_");
req.getContext().put("path","/update/json/docs");
rsp = new SolrQueryResponse();
p = new BufferingRequestProcessor(null);
loader = new JsonLoader();
loader.load(req, rsp, new ContentStreamBase.StringStream(doc), p);
assertEquals( 2, p.addCommands.size() );
String content = (String) p.addCommands.get(0).solrDoc.getFieldValue("_src_");
assertNotNull(content);
@SuppressWarnings({"rawtypes"})
Map obj = (Map) Utils.fromJSONString(content);
assertEquals(Boolean.TRUE, obj.get("bool"));
assertEquals("v0", obj.get("f0"));
assertNotNull(obj.get("f0"));
assertNotNull(obj.get("array"));
assertNotNull(obj.get("boosted"));
content = (String) p.addCommands.get(1).solrDoc.getFieldValue("_src_");
assertNotNull(content);
obj = (Map) Utils.fromJSONString(content);
assertEquals("v1", obj.get("f1"));
assertEquals("v2", obj.get("f2"));
assertTrue(obj.containsKey("f3"));
//TODO new test method
doc = "[{'id':'1'},{'id':'2'}]".replace('\'', '"');
req = req("srcField","_src_");
req.getContext().put("path","/update/json/docs");
rsp = new SolrQueryResponse();
p = new BufferingRequestProcessor(null);
loader = new JsonLoader();
loader.load(req, rsp, new ContentStreamBase.StringStream(doc), p);
assertEquals( 2, p.addCommands.size() );
content = (String) p.addCommands.get(0).solrDoc.getFieldValue("_src_");
assertNotNull(content);
obj = (Map) Utils.fromJSONString(content);
assertEquals("1", obj.get("id"));
content = (String) p.addCommands.get(1).solrDoc.getFieldValue("_src_");
assertNotNull(content);
obj = (Map) Utils.fromJSONString(content);
assertEquals("2", obj.get("id"));
//TODO new test method
String json = "{a:{" +
"b:[{c:c1, e:e1},{c:c2, e :e2, d:{p:q}}]," +
"x:y" +
"}}";
req = req("split", "/|/a/b" );
req.getContext().put("path","/update/json/docs");
rsp = new SolrQueryResponse();
p = new BufferingRequestProcessor(null);
loader = new JsonLoader();
loader.load(req, rsp, new ContentStreamBase.StringStream(json), p);
assertEquals( 1, p.addCommands.size() );
assertEquals("SolrInputDocument(fields: [" +
"b=[" +
"SolrInputDocument(fields: [c=c1, e=e1]), " +
"SolrInputDocument(fields: [c=c2, e=e2, d.p=q])], " +
"a.x=y" +
"])", p.addCommands.get(0).solrDoc.toString());
}
private static final String PARENT_TWO_CHILDREN_JSON = "{\n" +
" \"id\": \"1\",\n" +
" \"name\": \"i am the parent\",\n" +
" \"cat\": \"parent\",\n" +
" \"children\": [\n" +
" {\n" +
" \"id\": \"1.1\",\n" +
" \"name\": \"i am the 1st child\",\n" +
" \"cat\": \"child\"\n" +
" },\n" +
" {\n" +
" \"id\": \"1.2\",\n" +
" \"name\": \"i am the 2nd child\",\n" +
" \"cat\": \"child\",\n" +
" \"test_s\": \"test-new-label\",\n" +
" \"grandchildren\": [\n" +
" {\n" +
" \"id\": \"1.2.1\",\n" +
" \"name\": \"i am the grandchild\",\n" +
" \"cat\": \"grandchild\"\n" +
" }\n" +
" ]\n" +
" }\n" +
" ]\n" +
"}";
private static final String[] PARENT_TWO_CHILDREN_PARAMS = new String[] { "split", "/|/children|/children/grandchildren",
"f","$FQN:/**",
"f", "id:/children/id",
"f", "/name",
"f", "/children/name",
"f", "cat:/children/cat",
"f", "id:/children/grandchildren/id",
"f", "name:/children/grandchildren/name",
"f", "cat:/children/grandchildren/cat"};
@Test
public void testFewParentsJsonDoc() throws Exception {
String json = PARENT_TWO_CHILDREN_JSON;
SolrQueryRequest req;
SolrQueryResponse rsp;
BufferingRequestProcessor p;
JsonLoader loader;//multichild test case
final boolean array = random().nextBoolean();
StringBuilder b = new StringBuilder();
if (array) {
b.append("[");
}
final int passes = atLeast(2);
for (int i=1;i<=passes;i++){
b.append(json.replace("1",""+i));
if (array) {
b.append(i<passes ? "," :"]");
}
}
req = req(PARENT_TWO_CHILDREN_PARAMS);
req.getContext().put("path", "/update/json/docs");
rsp = new SolrQueryResponse();
p = new BufferingRequestProcessor(null);
loader = new JsonLoader();
loader.load(req, rsp, new ContentStreamBase.StringStream(b.toString()), p);
for (int i=1; i<=passes; i++){
final int ii = i;
UnaryOperator<String> s = (v)-> v.replace("1",""+ii);
final SolrInputDocument parent = p.addCommands.get(i-1).solrDoc;
assertOnlyValue(s.apply("1"), parent,"id");
assertOnlyValue("i am the parent", parent, "name");
assertOnlyValue("parent", parent, "cat");
@SuppressWarnings({"unchecked"})
List<SolrInputDocument> childDocs1 = (List) ((parent.getField("children")).getValue());
assertEquals(2, childDocs1.size());
{
final SolrInputDocument child1 = childDocs1.get(0);
assertOnlyValue(s.apply("1.1"), child1, "id");
assertOnlyValue(s.apply("i am the 1st child"), child1, "name");
assertOnlyValue("child", child1,"cat");
}
{
final SolrInputDocument child2 = childDocs1.get(1);
assertOnlyValue(s.apply("1.2"), child2, "id");
assertOnlyValue("i am the 2nd child", child2, "name");
assertOnlyValue("test-new-label", child2, "test_s");
assertOnlyValue("child", child2, "cat");
@SuppressWarnings({"unchecked"})
List<SolrInputDocument> childDocs2 = (List) ((child2.getField("grandchildren")).getValue());
assertEquals(1, childDocs2.size());
final SolrInputDocument grandChild = childDocs2.get(0);
assertOnlyValue(s.apply("1.2.1"), grandChild,"id");
assertOnlyValue("i am the grandchild", grandChild, "name");
assertOnlyValue("grandchild", grandChild, "cat");
}
}
}
private static void assertOnlyValue(String expected, SolrInputDocument doc, String field) {
assertEquals(Collections.singletonList(expected), doc.getFieldValues(field));
}
public void testAtomicUpdateFieldValue() throws Exception {
String str = "[{'id':'1', 'val_s':{'add':'foo'}}]".replace('\'', '"');
SolrQueryRequest req = req();
SolrQueryResponse rsp = new SolrQueryResponse();
BufferingRequestProcessor p = new BufferingRequestProcessor(null);
JsonLoader loader = new JsonLoader();
loader.load(req, rsp, new ContentStreamBase.StringStream(str), p);
assertEquals( 1, p.addCommands.size() );
AddUpdateCommand add = p.addCommands.get(0);
assertEquals(add.commitWithin, -1);
assertEquals(add.overwrite, true);
assertEquals("SolrInputDocument(fields: [id=1, val_s={add=foo}])", add.solrDoc.toString());
req.close();
}
@Test
public void testNullValues() throws Exception {
updateJ( json( "[{'id':'10','foo_s':null,'foo2_s':['hi',null,'there']}]" ), params("commit","true"));
assertJQ(req("q","id:10", "fl","foo_s,foo2_s")
,"/response/docs/[0]=={'foo2_s':['hi','there']}"
);
}
@Test
public void testBooleanValuesInAdd() throws Exception {
String str = "{'add':[{'id':'1','b1':true,'b2':false,'b3':[false,true]}]}".replace('\'', '"');
SolrQueryRequest req = req();
SolrQueryResponse rsp = new SolrQueryResponse();
BufferingRequestProcessor p = new BufferingRequestProcessor(null);
JsonLoader loader = new JsonLoader();
loader.load(req, rsp, new ContentStreamBase.StringStream(str), p);
assertEquals(1, p.addCommands.size());
AddUpdateCommand add = p.addCommands.get(0);
SolrInputDocument d = add.solrDoc;
SolrInputField f = d.getField("b1");
assertEquals(Boolean.TRUE, f.getValue());
f = d.getField("b2");
assertEquals(Boolean.FALSE, f.getValue());
f = d.getField("b3");
assertEquals(2, ((List)f.getValue()).size());
assertEquals(Boolean.FALSE, ((List)f.getValue()).get(0));
assertEquals(Boolean.TRUE, ((List)f.getValue()).get(1));
req.close();
}
@Test
public void testIntegerValuesInAdd() throws Exception {
String str = "{'add':[{'id':'1','i1':256,'i2':-5123456789,'i3':[0,1]}]}".replace('\'', '"');
SolrQueryRequest req = req();
SolrQueryResponse rsp = new SolrQueryResponse();
BufferingRequestProcessor p = new BufferingRequestProcessor(null);
JsonLoader loader = new JsonLoader();
loader.load(req, rsp, new ContentStreamBase.StringStream(str), p);
assertEquals(1, p.addCommands.size());
AddUpdateCommand add = p.addCommands.get(0);
SolrInputDocument d = add.solrDoc;
SolrInputField f = d.getField("i1");
assertEquals(256L, f.getValue());
f = d.getField("i2");
assertEquals(-5123456789L, f.getValue());
f = d.getField("i3");
assertEquals(2, ((List)f.getValue()).size());
assertEquals(0L, ((List)f.getValue()).get(0));
assertEquals(1L, ((List)f.getValue()).get(1));
req.close();
}
@Test
public void testDecimalValuesInAdd() throws Exception {
String str = "{'add':[{'id':'1','d1':256.78,'d2':-5123456789.0,'d3':0.0,'d3':1.0,'d4':1.7E-10}]}".replace('\'', '"');
SolrQueryRequest req = req();
SolrQueryResponse rsp = new SolrQueryResponse();
BufferingRequestProcessor p = new BufferingRequestProcessor(null);
JsonLoader loader = new JsonLoader();
loader.load(req, rsp, new ContentStreamBase.StringStream(str), p);
assertEquals(1, p.addCommands.size());
AddUpdateCommand add = p.addCommands.get(0);
SolrInputDocument d = add.solrDoc;
SolrInputField f = d.getField("d1");
assertEquals(256.78, f.getValue());
f = d.getField("d2");
assertEquals(-5123456789.0, f.getValue());
f = d.getField("d3");
assertEquals(2, ((List)f.getValue()).size());
assertTrue(((List)f.getValue()).contains(0.0));
assertTrue(((List) f.getValue()).contains(1.0));
f = d.getField("d4");
assertEquals(1.7E-10, f.getValue());
req.close();
}
@Test
public void testBigDecimalValuesInAdd() throws Exception {
String str = ("{'add':[{'id':'1','bd1':0.12345678901234567890123456789012345,"
+ "'bd2':12345678901234567890.12345678901234567890,'bd3':0.012345678901234567890123456789012345,"
+ "'bd3':123456789012345678900.012345678901234567890}]}").replace('\'', '"');
SolrQueryRequest req = req();
SolrQueryResponse rsp = new SolrQueryResponse();
BufferingRequestProcessor p = new BufferingRequestProcessor(null);
JsonLoader loader = new JsonLoader();
loader.load(req, rsp, new ContentStreamBase.StringStream(str), p);
assertEquals(1, p.addCommands.size());
AddUpdateCommand add = p.addCommands.get(0);
SolrInputDocument d = add.solrDoc;
SolrInputField f = d.getField("bd1");
assertTrue(f.getValue() instanceof String);
assertEquals("0.12345678901234567890123456789012345", f.getValue());
f = d.getField("bd2");
assertTrue(f.getValue() instanceof String);
assertEquals("12345678901234567890.12345678901234567890", f.getValue());
f = d.getField("bd3");
assertEquals(2, ((List)f.getValue()).size());
assertTrue(((List)f.getValue()).contains("0.012345678901234567890123456789012345"));
assertTrue(((List)f.getValue()).contains("123456789012345678900.012345678901234567890"));
req.close();
}
@Test
public void testBigIntegerValuesInAdd() throws Exception {
String str = ("{'add':[{'id':'1','bi1':123456789012345678901,'bi2':1098765432109876543210,"
+ "'bi3':[1234567890123456789012,10987654321098765432109]}]}").replace('\'', '"');
SolrQueryRequest req = req();
SolrQueryResponse rsp = new SolrQueryResponse();
BufferingRequestProcessor p = new BufferingRequestProcessor(null);
JsonLoader loader = new JsonLoader();
loader.load(req, rsp, new ContentStreamBase.StringStream(str), p);
assertEquals(1, p.addCommands.size());
AddUpdateCommand add = p.addCommands.get(0);
SolrInputDocument d = add.solrDoc;
SolrInputField f = d.getField("bi1");
assertTrue(f.getValue() instanceof String);
assertEquals("123456789012345678901", f.getValue());
f = d.getField("bi2");
assertTrue(f.getValue() instanceof String);
assertEquals("1098765432109876543210", f.getValue());
f = d.getField("bi3");
assertEquals(2, ((List)f.getValue()).size());
assertTrue(((List)f.getValue()).contains("1234567890123456789012"));
assertTrue(((List)f.getValue()).contains("10987654321098765432109"));
req.close();
}
@Test
public void testAddNonStringValues() throws Exception {
// BigInteger and BigDecimal should be typed as strings, since there is no direct support for them
updateJ(json( "[{'id':'1','boolean_b':false,'long_l':19,'double_d':18.6,'big_integer_s':12345678901234567890,"
+" 'big_decimal_s':0.1234567890123456789012345}]" ), params("commit","true"));
assertJQ(req("q","id:1", "fl","boolean_b,long_l,double_d,big_integer_s,big_decimal_s")
,"/response/docs/[0]=={'boolean_b':[false],'long_l':[19],'double_d':[18.6],"
+"'big_integer_s':['12345678901234567890'],"
+"'big_decimal_s':['0.1234567890123456789012345']}]}"
);
}
@Test
public void testAddBigIntegerValueToTrieField() throws Exception {
// Adding a BigInteger to a long field should fail
// BigInteger.longValue() returns only the low-order 64 bits.
ignoreException("big_integer_t");
SolrException ex = expectThrows(SolrException.class, () -> {
updateJ(json( "[{'id':'1','big_integer_tl':12345678901234567890}]" ), null);
});
assertTrue(ex.getCause() instanceof NumberFormatException);
// Adding a BigInteger to an integer field should fail
// BigInteger.intValue() returns only the low-order 32 bits.
ex = expectThrows(SolrException.class, () -> {
updateJ(json( "[{'id':'1','big_integer_ti':12345678901234567890}]" ), null);
});
assertTrue(ex.getCause() instanceof NumberFormatException);
unIgnoreException("big_integer_t");
}
@Test
public void testAddBigDecimalValueToTrieField() throws Exception {
// Adding a BigDecimal to a double field should succeed by reducing precision
updateJ(json( "[{'id':'1','big_decimal_td':100000000000000000000000000001234567890.0987654321}]" ),
params("commit", "true"));
assertJQ(req("q","id:1", "fl","big_decimal_td"),
"/response/docs/[0]=={'big_decimal_td':[1.0E38]}"
);
// Adding a BigDecimal to a float field should succeed by reducing precision
updateJ(json( "[{'id':'2','big_decimal_tf':100000000000000000000000000001234567890.0987654321}]" ),
params("commit", "true"));
assertJQ(req("q","id:2", "fl","big_decimal_tf"),
"/response/docs/[0]=={'big_decimal_tf':[1.0E38]}"
);
}
// The delete syntax was both extended for simplification in 4.0
@Test
public void testDeleteSyntax() throws Exception {
String str = "{'delete':10"
+"\n ,'delete':'20'"
+"\n ,'delete':['30','40']"
+"\n ,'delete':{'id':50, '_version_':12345}"
+"\n ,'delete':[{'id':60, '_version_':67890}, {'id':70, '_version_':77777}, {'query':'id:80', '_version_':88888}]"
+"\n ,'delete':{'id':90, '_route_':'shard1', '_version_':88888}"
+ "\n}\n";
str = str.replace('\'', '"');
SolrQueryRequest req = req();
SolrQueryResponse rsp = new SolrQueryResponse();
BufferingRequestProcessor p = new BufferingRequestProcessor(null);
JsonLoader loader = new JsonLoader();
loader.load(req, rsp, new ContentStreamBase.StringStream(str), p);
// DELETE COMMANDS
assertEquals( 9, p.deleteCommands.size() );
DeleteUpdateCommand delete = p.deleteCommands.get( 0 );
assertEquals( delete.id, "10" );
assertEquals( delete.query, null );
assertEquals( delete.commitWithin, -1);
delete = p.deleteCommands.get( 1 );
assertEquals( delete.id, "20" );
assertEquals( delete.query, null );
assertEquals( delete.commitWithin, -1);
delete = p.deleteCommands.get( 2 );
assertEquals( delete.id, "30" );
assertEquals( delete.query, null );
assertEquals( delete.commitWithin, -1);
delete = p.deleteCommands.get( 3 );
assertEquals( delete.id, "40" );
assertEquals( delete.query, null );
assertEquals( delete.commitWithin, -1);
delete = p.deleteCommands.get( 4 );
assertEquals( delete.id, "50" );
assertEquals( delete.query, null );
assertEquals( delete.getVersion(), 12345L);
delete = p.deleteCommands.get( 5 );
assertEquals( delete.id, "60" );
assertEquals( delete.query, null );
assertEquals( delete.getVersion(), 67890L);
delete = p.deleteCommands.get( 6 );
assertEquals( delete.id, "70" );
assertEquals( delete.query, null );
assertEquals( delete.getVersion(), 77777L);
delete = p.deleteCommands.get( 7 );
assertEquals( delete.id, null );
assertEquals( delete.query, "id:80" );
assertEquals(delete.getVersion(), 88888L);
delete = p.deleteCommands.get(8);
assertEquals(delete.id, "90");
assertEquals(delete.query, null);
assertEquals(delete.getRoute(), "shard1");
assertEquals(delete.getVersion(), 88888L);
req.close();
}
private static final String SIMPLE_ANON_CHILD_DOCS_JSON = "{\n" +
" \"add\": {\n" +
" \"doc\": {\n" +
" \"id\": \"1\",\n" +
" \"_childDocuments_\": [\n" +
" {\n" +
" \"id\": \"2\"\n" +
" },\n" +
" {\n" +
" \"id\": \"3\",\n" +
" \"foo_i\": [666,777]\n" +
" }\n" +
" ]\n" +
" }\n" +
" }\n" +
"}";
@Test
public void testSimpleAnonymousChildDocs() throws Exception {
checkTwoAnonymousChildDocs(SIMPLE_ANON_CHILD_DOCS_JSON, true);
}
@Test
public void testSimpleChildDocs() throws Exception {
checkTwoAnonymousChildDocs(SIMPLE_ANON_CHILD_DOCS_JSON, false);
}
private static final String DUP_KEYS_ANON_CHILD_DOCS_JSON = "{\n" +
" \"add\": {\n" +
" \"doc\": {\n" +
" \"_childDocuments_\": [\n" +
" {\n" +
" \"id\": \"2\"\n" +
" }\n" +
" ],\n" +
" \"id\": \"1\",\n" +
" \"_childDocuments_\": [\n" +
" {\n" +
" \"id\": \"3\",\n" +
" \"foo_i\": 666,\n" +
" \"foo_i\": 777\n" +
" }\n" +
" ]\n" +
" }\n" +
" }\n" +
"}";
@Test
public void testDupKeysAnonymousChildDocs() throws Exception {
checkTwoAnonymousChildDocs(DUP_KEYS_ANON_CHILD_DOCS_JSON, true);
}
@Test
public void testDupKeysChildDocs() throws Exception {
checkTwoAnonymousChildDocs(DUP_KEYS_ANON_CHILD_DOCS_JSON, false);
}
// rawJsonStr has "_childDocuments_" key. if anonChildDocs then we want to test with something else.
private void checkTwoAnonymousChildDocs(String rawJsonStr, boolean anonChildDocs) throws Exception {
if (!anonChildDocs) {
rawJsonStr = rawJsonStr.replaceAll("_childDocuments_", "childLabel");
}
SolrQueryRequest req = req("commit","true");
SolrQueryResponse rsp = new SolrQueryResponse();
BufferingRequestProcessor p = new BufferingRequestProcessor(null);
JsonLoader loader = new JsonLoader();
loader.load(req, rsp, new ContentStreamBase.StringStream(rawJsonStr), p);
assertEquals( 1, p.addCommands.size() );
AddUpdateCommand add = p.addCommands.get(0);
SolrInputDocument d = add.solrDoc;
SolrInputField f = d.getField( "id" );
assertEquals("1", f.getValue());
SolrInputDocument cd;
if (anonChildDocs) {
cd = d.getChildDocuments().get(0);
} else {
cd = (SolrInputDocument) (d.getField("childLabel")).getFirstValue();
}
SolrInputField cf = cd.getField( "id" );
assertEquals("2", cf.getValue());
if (anonChildDocs) {
cd = d.getChildDocuments().get(1);
} else {
cd = (SolrInputDocument)((List)(d.getField("childLabel")).getValue()).get(1);
}
cf = cd.getField( "id" );
assertEquals("3", cf.getValue());
cf = cd.getField( "foo_i" );
assertEquals(2, cf.getValueCount());
assertEquals(new Object[] {666L,777L}, cf.getValues().toArray());
req.close();
}
@Test
public void testEmptyAnonymousChildDocs() throws Exception {
String str = "{\n" +
" \"add\": {\n" +
" \"doc\": {\n" +
" \"id\": \"1\",\n" +
" \"_childDocuments_\": []\n" +
" }\n" +
" }\n" +
"}";
SolrQueryRequest req = req("commit","true");
SolrQueryResponse rsp = new SolrQueryResponse();
BufferingRequestProcessor p = new BufferingRequestProcessor(null);
JsonLoader loader = new JsonLoader();
loader.load(req, rsp, new ContentStreamBase.StringStream(str), p);
assertEquals( 1, p.addCommands.size() );
AddUpdateCommand add = p.addCommands.get(0);
SolrInputDocument d = add.solrDoc;
SolrInputField f = d.getField( "id" );
assertEquals("1", f.getValue());
List<SolrInputDocument> cd = d.getChildDocuments();
assertNull(cd);
req.close();
}
@Test
public void testAnonymousGrandChildDocs() throws Exception {
String str = "{\n" +
" \"add\": {\n" +
" \"doc\": {\n" +
" \"id\": \"1\",\n" +
" \"_childDocuments_\": [\n" +
" {\n" +
" \"id\": \"2\",\n" +
" \"_childDocuments_\": [\n" +
" {\n" +
" \"id\": \"4\",\n" +
" \"foo_s\": \"Baz\"\n" +
" }\n" +
" ],\n" +
" \"foo_s\": \"Yaz\"\n" +
" },\n" +
" {\n" +
" \"id\": \"3\",\n" +
" \"foo_s\": \"Bar\"\n" +
" }\n" +
" ]\n" +
" }\n" +
" }\n" +
"}";
SolrQueryRequest req = req("commit","true");
SolrQueryResponse rsp = new SolrQueryResponse();
BufferingRequestProcessor p = new BufferingRequestProcessor(null);
JsonLoader loader = new JsonLoader();
loader.load(req, rsp, new ContentStreamBase.StringStream(str), p);
assertEquals( 1, p.addCommands.size() );
AddUpdateCommand add = p.addCommands.get(0);
SolrInputDocument one = add.solrDoc;
assertEquals("1", one.getFieldValue("id"));
SolrInputDocument two = one.getChildDocuments().get(0);
assertEquals("2", two.getFieldValue("id"));
assertEquals("Yaz", two.getFieldValue("foo_s"));
SolrInputDocument four = two.getChildDocuments().get(0);
assertEquals("4", four.getFieldValue("id"));
assertEquals("Baz", four.getFieldValue("foo_s"));
SolrInputDocument three = one.getChildDocuments().get(1);
assertEquals("3", three.getFieldValue("id"));
assertEquals("Bar", three.getFieldValue("foo_s"));
req.close();
}
@Test
public void testChildDocs() throws Exception {
String str = "{\n" +
" \"add\": {\n" +
" \"doc\": {\n" +
" \"id\": \"1\",\n" +
" \"children\": [\n" +
" {\n" +
" \"id\": \"2\",\n" +
" \"foo_s\": \"Yaz\"\n" +
" },\n" +
" {\n" +
" \"id\": \"3\",\n" +
" \"foo_s\": \"Bar\"\n" +
" }\n" +
" ]\n" +
" }\n" +
" }\n" +
"}";
SolrQueryRequest req = req("commit","true");
SolrQueryResponse rsp = new SolrQueryResponse();
BufferingRequestProcessor p = new BufferingRequestProcessor(null);
JsonLoader loader = new JsonLoader();
loader.load(req, rsp, new ContentStreamBase.StringStream(str), p);
assertEquals( 1, p.addCommands.size() );
AddUpdateCommand add = p.addCommands.get(0);
SolrInputDocument one = add.solrDoc;
assertEquals("1", one.getFieldValue("id"));
@SuppressWarnings({"unchecked"})
List<SolrInputDocument> children = (List) one.getFieldValues("children");
SolrInputDocument two = children.get(0);
assertEquals("2", two.getFieldValue("id"));
assertEquals("Yaz", two.getFieldValue("foo_s"));
SolrInputDocument three = children.get(1);
assertEquals("3", three.getFieldValue("id"));
assertEquals("Bar", three.getFieldValue("foo_s"));
req.close();
}
@Test
public void testSingleRelationalChildDoc() throws Exception {
String str = "{\n" +
" \"add\": {\n" +
" \"doc\": {\n" +
" \"id\": \"1\",\n" +
" \"child1\": \n" +
" {\n" +
" \"id\": \"2\",\n" +
" \"foo_s\": \"Yaz\"\n" +
" },\n" +
" }\n" +
" }\n" +
"}";
SolrQueryRequest req = req("commit","true");
SolrQueryResponse rsp = new SolrQueryResponse();
BufferingRequestProcessor p = new BufferingRequestProcessor(null);
JsonLoader loader = new JsonLoader();
loader.load(req, rsp, new ContentStreamBase.StringStream(str), p);
assertEquals( 1, p.addCommands.size() );
AddUpdateCommand add = p.addCommands.get(0);
SolrInputDocument one = add.solrDoc;
assertEquals("1", one.getFieldValue("id"));
assertTrue(one.keySet().contains("child1"));
SolrInputDocument two = (SolrInputDocument) one.getField("child1").getValue();
assertEquals("2", two.getFieldValue("id"));
assertEquals("Yaz", two.getFieldValue("foo_s"));
req.close();
}
}