diff options
author | Geir Storli <geirst@oath.com> | 2019-01-10 10:41:28 +0000 |
---|---|---|
committer | gjoranv <gv@oath.com> | 2019-01-21 15:09:30 +0100 |
commit | 5227880b0749a243d396f3443e0d988abcfae7af (patch) | |
tree | 83b533746e9f1e717dd2991e6b823cbfd7ce93bc | |
parent | 78d3b485ebc152b238c6c910fc262fa93561aff9 (diff) |
Render single value position as object to match how top-level position fields are rendered.
5 files changed, 70 insertions, 58 deletions
diff --git a/container-search/src/main/java/com/yahoo/prelude/fastsearch/XMLField.java b/container-search/src/main/java/com/yahoo/prelude/fastsearch/XMLField.java index cb115502468..d768dda2657 100644 --- a/container-search/src/main/java/com/yahoo/prelude/fastsearch/XMLField.java +++ b/container-search/src/main/java/com/yahoo/prelude/fastsearch/XMLField.java @@ -31,10 +31,10 @@ public class XMLField extends DocsumField { @Override public Object convert(Inspector value) { /* In Vespa 6 the backend will send an XML-formatted string to represent - * positions data. This will change in next version to sending an array - * of objects instead, suitable for the PositionsData class. + * positions data. This will change in next version to sending an object + * or an array of objects instead, suitable for the PositionsData class. */ - if (value.type() == Type.ARRAY) { + if (value.type() == Type.OBJECT || value.type() == Type.ARRAY) { return new PositionsData(value); } return convert(value.asString("")); diff --git a/container-search/src/main/java/com/yahoo/search/result/PositionsData.java b/container-search/src/main/java/com/yahoo/search/result/PositionsData.java index a07eaa2438d..483849a5435 100644 --- a/container-search/src/main/java/com/yahoo/search/result/PositionsData.java +++ b/container-search/src/main/java/com/yahoo/search/result/PositionsData.java @@ -17,8 +17,8 @@ public class PositionsData implements Inspectable, JsonProducer, XmlProducer { public PositionsData(Inspector value) { this.value = value; - if (value.type() != Type.ARRAY) { - throw new IllegalArgumentException("PositionsData expects an array of positions, got: "+value); + if (value.type() != Type.OBJECT && value.type() != Type.ARRAY) { + throw new IllegalArgumentException("PositionsData expects a position or an array of positions, got: "+value); } } @@ -38,27 +38,35 @@ public class PositionsData implements Inspectable, JsonProducer, XmlProducer { @Override public StringBuilder writeXML(StringBuilder target) { - for (int i = 0; i < value.entryCount(); i++) { - Inspector pos = value.entry(i); - target.append("<position "); - for (java.util.Map.Entry<String, Inspector> entry : pos.fields()) { - Inspector v = entry.getValue(); - if (v.type() == Type.STRING) { - target.append(entry.getKey()); - target.append("=\""); - target.append(entry.getValue().asString()); - target.append("\" "); - } - if (v.type() == Type.LONG) { - target.append(entry.getKey()); - target.append("=\""); - target.append(entry.getValue().asLong()); - target.append("\" "); - } + if (value.type() == Type.OBJECT) { + writeXML(value.inspect(), target); + } else { + for (int i = 0; i < value.entryCount(); i++) { + Inspector pos = value.entry(i); + writeXML(pos, target); } - target.append("/>"); } return target; } + private static void writeXML(Inspector pos, StringBuilder target) { + target.append("<position "); + for (java.util.Map.Entry<String, Inspector> entry : pos.fields()) { + Inspector v = entry.getValue(); + if (v.type() == Type.STRING) { + target.append(entry.getKey()); + target.append("=\""); + target.append(entry.getValue().asString()); + target.append("\" "); + } + if (v.type() == Type.LONG) { + target.append(entry.getKey()); + target.append("=\""); + target.append(entry.getValue().asLong()); + target.append("\" "); + } + } + target.append("/>"); + } + } diff --git a/container-search/src/test/java/com/yahoo/search/result/PositionsDataTestCase.java b/container-search/src/test/java/com/yahoo/search/result/PositionsDataTestCase.java index c77ff2eca3c..91c8acbab12 100644 --- a/container-search/src/test/java/com/yahoo/search/result/PositionsDataTestCase.java +++ b/container-search/src/test/java/com/yahoo/search/result/PositionsDataTestCase.java @@ -5,8 +5,6 @@ import com.yahoo.data.access.simple.Value; import static org.junit.Assert.*; -import org.junit.After; -import org.junit.Before; import org.junit.Test; /** @@ -15,41 +13,43 @@ import org.junit.Test; public class PositionsDataTestCase { @Test - public void testRendering() { - Value.ArrayValue arr = new Value.ArrayValue(); - Value.ObjectValue p1 = new Value.ObjectValue(); - p1.put("x", new Value.LongValue(-122057174)); - p1.put("y", new Value.LongValue(37374821)); - p1.put("latlong", new Value.StringValue("N37.374821;W122.057174")); - arr.add(p1); + public void testRenderingOfSinglePosition() { + Value.ObjectValue pos = createPosition(-122057174, 37374821, "N37.374821;W122.057174"); - PositionsData pd = new PositionsData(arr.inspect()); + PositionsData pd = new PositionsData(pos.inspect()); - String rendered = pd.toXML(); - String correct = "<position x=\"-122057174\" y=\"37374821\" latlong=\"N37.374821;W122.057174\" />"; - assertEquals(correct, rendered); + assertXml("<position x=\"-122057174\" y=\"37374821\" latlong=\"N37.374821;W122.057174\" />", pd); + assertJson("{\"x\":-122057174,\"y\":37374821,\"latlong\":\"N37.374821;W122.057174\"}", pd); + } + + @Test + public void testRenderingOfMultiplePositions() { + Value.ArrayValue arr = new Value.ArrayValue(); + arr.add(createPosition(-122057174, 37374821, "N37.374821;W122.057174")); + arr.add(createPosition(3, -7, "S0.000007;E0.000003")); - rendered = pd.toJson(); - correct = "[{\"x\":-122057174,\"y\":37374821,\"latlong\":\"N37.374821;W122.057174\"}]"; - assertEquals(correct, rendered); + PositionsData pd = new PositionsData(arr.inspect()); - Value.ObjectValue p2 = new Value.ObjectValue(); - p2.put("x", new Value.LongValue(3)); - p2.put("y", new Value.LongValue(-7)); - p2.put("latlong", new Value.StringValue("S0.000007;E0.000003")); - arr.add(p2); + assertXml("<position x=\"-122057174\" y=\"37374821\" latlong=\"N37.374821;W122.057174\" />" + + "<position x=\"3\" y=\"-7\" latlong=\"S0.000007;E0.000003\" />", pd); + assertJson("[{\"x\":-122057174,\"y\":37374821,\"latlong\":\"N37.374821;W122.057174\"}," + + "{\"x\":3,\"y\":-7,\"latlong\":\"S0.000007;E0.000003\"}]", pd); + } - pd = new PositionsData(arr.inspect()); + private Value.ObjectValue createPosition(long x, long y, String latlong) { + Value.ObjectValue result = new Value.ObjectValue(); + result.put("x", new Value.LongValue(x)); + result.put("y", new Value.LongValue(y)); + result.put("latlong", new Value.StringValue(latlong)); + return result; + } - rendered = pd.toXML(); - correct = "<position x=\"-122057174\" y=\"37374821\" latlong=\"N37.374821;W122.057174\" />" + - "<position x=\"3\" y=\"-7\" latlong=\"S0.000007;E0.000003\" />"; - assertEquals(correct, rendered); + private void assertXml(String expected, PositionsData pd) { + assertEquals(expected, pd.toXML()); + } - rendered = pd.toJson(); - correct = "[{\"x\":-122057174,\"y\":37374821,\"latlong\":\"N37.374821;W122.057174\"}," + - "{\"x\":3,\"y\":-7,\"latlong\":\"S0.000007;E0.000003\"}]"; - assertEquals(correct, rendered); + private void assertJson(String expected, PositionsData pd) { + assertEquals(expected, pd.toJson()); } } diff --git a/searchcore/src/tests/proton/docsummary/docsummary.cpp b/searchcore/src/tests/proton/docsummary/docsummary.cpp index 4b70b4797af..40c2733d230 100644 --- a/searchcore/src/tests/proton/docsummary/docsummary.cpp +++ b/searchcore/src/tests/proton/docsummary/docsummary.cpp @@ -1108,7 +1108,7 @@ Test::requireThatPositionsAreUsed() EXPECT_EQUAL(1u, rep->docsums[0].docid); EXPECT_EQUAL(gid1, rep->docsums[0].gid); EXPECT_TRUE(assertSlime("{sp2:'1047758'" - ",sp2x:[{x:1002, y:1003, latlong:'N0.001003;E0.001002'}]" + ",sp2x:{x:1002, y:1003, latlong:'N0.001003;E0.001002'}" ",ap2:[1047806,1048322]" ",ap2x:[{x:1006, y:1007, latlong:'N0.001007;E0.001006'}," "{x:1008, y:1009, latlong:'N0.001009;E0.001008'}]" diff --git a/searchsummary/src/vespa/searchsummary/docsummary/positionsdfw.cpp b/searchsummary/src/vespa/searchsummary/docsummary/positionsdfw.cpp index c968158b9c2..6b003553f49 100644 --- a/searchsummary/src/vespa/searchsummary/docsummary/positionsdfw.cpp +++ b/searchsummary/src/vespa/searchsummary/docsummary/positionsdfw.cpp @@ -157,10 +157,14 @@ insertFromAttr(const attribute::IAttributeVector &attribute, uint32_t docid, ves uint32_t numValues = pos.size(); LOG(debug, "docid=%d, numValues=%d", docid, numValues); if (numValues > 0) { - vespalib::slime::Cursor &arr = target.insertArray(); - for (uint32_t i = 0; i < numValues; i++) { - vespalib::slime::ArrayInserter ai(arr); - insertPos(pos[i], ai); + if (attribute.getCollectionType() == attribute::CollectionType::SINGLE) { + insertPos(pos[0], target); + } else { + vespalib::slime::Cursor &arr = target.insertArray(); + for (uint32_t i = 0; i < numValues; i++) { + vespalib::slime::ArrayInserter ai(arr); + insertPos(pos[i], ai); + } } } } |