Scripts: exposed _uid, _id and _type fields as stored fields (_fields notation)

The _uid field wasn't available in a script despite it's always stored. Made it available and made available also _id and _type fields that are deducted from it.

Closes #6406
This commit is contained in:
javanna 2014-06-04 11:36:47 +02:00 committed by Luca Cavanna
parent 838142646f
commit 21772e0bf9
3 changed files with 97 additions and 6 deletions

View File

@ -136,7 +136,7 @@ public abstract class FieldsVisitor extends StoredFieldVisitor {
uid = null;
}
private void addValue(String name, Object value) {
void addValue(String name, Object value) {
if (fieldsValues == null) {
fieldsValues = newHashMap();
}

View File

@ -20,6 +20,9 @@ package org.elasticsearch.index.fieldvisitor;
import org.apache.lucene.index.FieldInfo;
import org.elasticsearch.index.mapper.FieldMapper;
import org.elasticsearch.index.mapper.internal.IdFieldMapper;
import org.elasticsearch.index.mapper.internal.TypeFieldMapper;
import org.elasticsearch.index.mapper.internal.UidFieldMapper;
import java.io.IOException;
import java.util.List;
@ -36,12 +39,15 @@ public class SingleFieldsVisitor extends FieldsVisitor {
@Override
public Status needsField(FieldInfo fieldInfo) throws IOException {
// TODO we can potentially skip if we processed a field, the question is if it works for multi valued fields
if (fieldInfo.name.equals(field)) {
return Status.YES;
} else {
return Status.NO;
}
if (fieldInfo.name.equals(UidFieldMapper.NAME)) {
if (TypeFieldMapper.NAME.equals(field) || IdFieldMapper.NAME.equals(field)) {
return Status.YES;
}
}
return Status.NO;
}
public void reset(String field) {
@ -50,6 +56,14 @@ public class SingleFieldsVisitor extends FieldsVisitor {
}
public void postProcess(FieldMapper mapper) {
if (uid != null) {
switch (field) {
case UidFieldMapper.NAME: addValue(field, uid.toString());
case IdFieldMapper.NAME: addValue(field, uid.id());
case TypeFieldMapper.NAME: addValue(field, uid.type());
}
}
if (fieldsValues == null) {
return;
}

View File

@ -19,6 +19,7 @@
package org.elasticsearch.search.fields;
import org.elasticsearch.action.index.IndexRequestBuilder;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.Base64;
@ -147,14 +148,17 @@ public class SearchFieldsTests extends ElasticsearchIntegrationTest {
assertThat(response.getHits().totalHits(), equalTo(3l));
assertThat(response.getHits().getAt(0).isSourceEmpty(), equalTo(true));
assertThat(response.getHits().getAt(0).id(), equalTo("1"));
assertThat(response.getHits().getAt(0).fields().size(), equalTo(3));
assertThat((Double) response.getHits().getAt(0).fields().get("sNum1").values().get(0), equalTo(1.0));
assertThat((Double) response.getHits().getAt(0).fields().get("sNum1_field").values().get(0), equalTo(1.0));
assertThat((Long) response.getHits().getAt(0).fields().get("date1").values().get(0), equalTo(0l));
assertThat(response.getHits().getAt(1).id(), equalTo("2"));
assertThat(response.getHits().getAt(1).fields().size(), equalTo(3));
assertThat((Double) response.getHits().getAt(1).fields().get("sNum1").values().get(0), equalTo(2.0));
assertThat((Double) response.getHits().getAt(1).fields().get("sNum1_field").values().get(0), equalTo(2.0));
assertThat((Long) response.getHits().getAt(1).fields().get("date1").values().get(0), equalTo(25000l));
assertThat(response.getHits().getAt(2).id(), equalTo("3"));
assertThat(response.getHits().getAt(2).fields().size(), equalTo(3));
assertThat((Double) response.getHits().getAt(2).fields().get("sNum1").values().get(0), equalTo(3.0));
assertThat((Double) response.getHits().getAt(2).fields().get("sNum1_field").values().get(0), equalTo(3.0));
assertThat((Long) response.getHits().getAt(2).fields().get("date1").values().get(0), equalTo(120000l));
@ -169,13 +173,86 @@ public class SearchFieldsTests extends ElasticsearchIntegrationTest {
assertThat(response.getHits().totalHits(), equalTo(3l));
assertThat(response.getHits().getAt(0).id(), equalTo("1"));
assertThat(response.getHits().getAt(0).fields().size(), equalTo(1));
assertThat((Double) response.getHits().getAt(0).fields().get("sNum1").values().get(0), equalTo(2.0));
assertThat(response.getHits().getAt(1).id(), equalTo("2"));
assertThat(response.getHits().getAt(1).fields().size(), equalTo(1));
assertThat((Double) response.getHits().getAt(1).fields().get("sNum1").values().get(0), equalTo(4.0));
assertThat(response.getHits().getAt(2).id(), equalTo("3"));
assertThat(response.getHits().getAt(2).fields().size(), equalTo(1));
assertThat((Double) response.getHits().getAt(2).fields().get("sNum1").values().get(0), equalTo(6.0));
}
@Test
public void testUidBasedScriptFields() throws Exception {
createIndex("test");
ensureYellow();
int numDocs = randomIntBetween(1, 30);
IndexRequestBuilder[] indexRequestBuilders = new IndexRequestBuilder[numDocs];
for (int i = 0; i < numDocs; i++) {
indexRequestBuilders[i] = client().prepareIndex("test", "type1", Integer.toString(i))
.setSource(jsonBuilder().startObject().field("num1", i).endObject());
}
indexRandom(true, indexRequestBuilders);
SearchResponse response = client().prepareSearch()
.setQuery(matchAllQuery()).addSort("num1", SortOrder.ASC).setSize(numDocs)
.addScriptField("uid", "_fields._uid.value").get();
assertNoFailures(response);
assertThat(response.getHits().totalHits(), equalTo((long)numDocs));
for (int i = 0; i < numDocs; i++) {
assertThat(response.getHits().getAt(i).id(), equalTo(Integer.toString(i)));
assertThat(response.getHits().getAt(i).fields().size(), equalTo(1));
assertThat((String)response.getHits().getAt(i).fields().get("uid").value(), equalTo("type1#" + Integer.toString(i)));
}
response = client().prepareSearch()
.setQuery(matchAllQuery()).addSort("num1", SortOrder.ASC).setSize(numDocs)
.addScriptField("id", "_fields._id.value").get();
assertNoFailures(response);
assertThat(response.getHits().totalHits(), equalTo((long)numDocs));
for (int i = 0; i < numDocs; i++) {
assertThat(response.getHits().getAt(i).id(), equalTo(Integer.toString(i)));
assertThat(response.getHits().getAt(i).fields().size(), equalTo(1));
assertThat((String)response.getHits().getAt(i).fields().get("id").value(), equalTo(Integer.toString(i)));
}
response = client().prepareSearch()
.setQuery(matchAllQuery()).addSort("num1", SortOrder.ASC).setSize(numDocs)
.addScriptField("type", "_fields._type.value").get();
assertNoFailures(response);
assertThat(response.getHits().totalHits(), equalTo((long)numDocs));
for (int i = 0; i < numDocs; i++) {
assertThat(response.getHits().getAt(i).id(), equalTo(Integer.toString(i)));
assertThat(response.getHits().getAt(i).fields().size(), equalTo(1));
assertThat((String)response.getHits().getAt(i).fields().get("type").value(), equalTo("type1"));
}
response = client().prepareSearch()
.setQuery(matchAllQuery()).addSort("num1", SortOrder.ASC).setSize(numDocs)
.addScriptField("id", "_fields._id.value")
.addScriptField("uid", "_fields._uid.value")
.addScriptField("type", "_fields._type.value").get();
assertNoFailures(response);
assertThat(response.getHits().totalHits(), equalTo((long)numDocs));
for (int i = 0; i < numDocs; i++) {
assertThat(response.getHits().getAt(i).id(), equalTo(Integer.toString(i)));
assertThat(response.getHits().getAt(i).fields().size(), equalTo(3));
assertThat((String)response.getHits().getAt(i).fields().get("uid").value(), equalTo("type1#" + Integer.toString(i)));
assertThat((String)response.getHits().getAt(i).fields().get("type").value(), equalTo("type1"));
assertThat((String)response.getHits().getAt(i).fields().get("id").value(), equalTo(Integer.toString(i)));
}
}
@Test
public void testScriptFieldUsingSource() throws Exception {
createIndex("test");
@ -213,12 +290,12 @@ public class SearchFieldsTests extends ElasticsearchIntegrationTest {
assertThat(sObj2Arr2.get(0).toString(), equalTo("arr_value1"));
assertThat(sObj2Arr2.get(1).toString(), equalTo("arr_value2"));
sObj2Arr2 = (List) response.getHits().getAt(0).field("s_obj2_arr2").value();
sObj2Arr2 = response.getHits().getAt(0).field("s_obj2_arr2").value();
assertThat(sObj2Arr2.size(), equalTo(2));
assertThat(sObj2Arr2.get(0).toString(), equalTo("arr_value1"));
assertThat(sObj2Arr2.get(1).toString(), equalTo("arr_value2"));
List sObj2Arr3 = (List) response.getHits().getAt(0).field("s_arr3").value();
List sObj2Arr3 = response.getHits().getAt(0).field("s_arr3").value();
assertThat(((Map) sObj2Arr3.get(0)).get("arr3_field1").toString(), equalTo("arr3_value1"));
}