SOLR-5183: JSON updates now support nested child documents using a "_childDocument_" object key

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1572797 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Chris M. Hostetter 2014-02-28 01:02:23 +00:00
parent 173daaedef
commit 6b1f3f0bb2
3 changed files with 190 additions and 24 deletions

View File

@ -82,8 +82,12 @@ Detailed Change List
New Features
----------------------
* SOLR-5130: Implement addReplica Collections API (Noble Paul)
* SOLR-5183: JSON updates now support nested child documents using a
"_childDocument_" object key. (Varun Thacker, hossman)
Bug Fixes
----------------------

View File

@ -53,7 +53,8 @@ import org.slf4j.LoggerFactory;
*/
public class JsonLoader extends ContentStreamLoader {
final static Logger log = LoggerFactory.getLogger( JsonLoader.class );
private static final String CHILD_DOC_KEY = "_childDocuments_";
@Override
public String getDefaultWT() {
return "json";
@ -409,35 +410,40 @@ public class JsonLoader extends ContentStreamLoader {
+" at ["+parser.getPosition()+"]" );
}
}
private SolrInputDocument parseDoc(int ev) throws IOException {
assert ev == JSONParser.OBJECT_START;
SolrInputDocument sdoc = new SolrInputDocument();
for (;;) {
SolrInputField sif = parseField();
if (sif == null) return sdoc;
// pulling out hte pieces may seem weird, but it's because
// SolrInputDocument.addField will do the right thing
// if the doc already has another value for this field
// (ie: repeating fieldname keys)
sdoc.addField(sif.getName(), sif.getValue(), sif.getBoost());
ev = parser.nextEvent();
if (ev == JSONParser.OBJECT_END) {
return sdoc;
}
String fieldName = parser.getString();
if(fieldName.equals(JsonLoader.CHILD_DOC_KEY)) {
ev = parser.nextEvent();
assertEvent(ev, JSONParser.ARRAY_START);
while( (ev = parser.nextEvent()) != JSONParser.ARRAY_END ) {
assertEvent(ev, JSONParser.OBJECT_START);
sdoc.addChildDocument(parseDoc(ev));
}
} else {
SolrInputField sif = new SolrInputField(fieldName);
parseFieldValue(sif);
// pulling out the pieces may seem weird, but it's because
// SolrInputDocument.addField will do the right thing
// if the doc already has another value for this field
// (ie: repeating fieldname keys)
sdoc.addField(sif.getName(), sif.getValue(), sif.getBoost());
}
}
}
private SolrInputField parseField() throws IOException {
int ev = parser.nextEvent();
if (ev == JSONParser.OBJECT_END) {
return null;
}
String fieldName = parser.getString();
SolrInputField sif = new SolrInputField(fieldName);
parseFieldValue(sif);
return sif;
}
private void parseFieldValue(SolrInputField sif) throws IOException {
int ev = parser.nextEvent();
if (ev == JSONParser.OBJECT_START) {

View File

@ -547,5 +547,161 @@ public class JsonLoaderTest extends SolrTestCaseJ4 {
req.close();
}
@Test
public void testSimpleChildDocs() throws Exception {
String str = "{\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" +
"}";
checkTwoChildDocs(str);
}
@Test
public void testDupKeysChildDocs() throws Exception {
String str = "{\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" +
"}";
checkTwoChildDocs(str);
}
private void checkTwoChildDocs(String rawJsonStr) throws Exception {
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 = d.getChildDocuments().get(0);
SolrInputField cf = cd.getField( "id" );
assertEquals("2", cf.getValue());
cd = d.getChildDocuments().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 testEmptyChildDocs() 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 testGrandChildDocs() 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();
}
}