Search in sources :

Example 1 with SearchHitField

use of org.elasticsearch.search.SearchHitField in project elasticsearch by elastic.

the class TopHitsIT method testNestedFetchFeatures.

public void testNestedFetchFeatures() {
    String hlType = randomFrom("plain", "fvh", "postings");
    HighlightBuilder.Field hlField = new HighlightBuilder.Field("comments.message").highlightQuery(matchQuery("comments.message", "comment")).forceSource(// randomly from stored field or _source
    randomBoolean()).highlighterType(hlType);
    SearchResponse searchResponse = client().prepareSearch("articles").setQuery(nestedQuery("comments", matchQuery("comments.message", "comment").queryName("test"), ScoreMode.Avg)).addAggregation(nested("to-comments", "comments").subAggregation(topHits("top-comments").size(1).highlighter(new HighlightBuilder().field(hlField)).explain(true).fieldDataField("comments.user").scriptField("script", new Script(ScriptType.INLINE, MockScriptEngine.NAME, "5", Collections.emptyMap())).fetchSource("comments.message", null).version(true).sort("comments.date", SortOrder.ASC))).get();
    assertHitCount(searchResponse, 2);
    Nested nested = searchResponse.getAggregations().get("to-comments");
    assertThat(nested.getDocCount(), equalTo(4L));
    SearchHits hits = ((TopHits) nested.getAggregations().get("top-comments")).getHits();
    assertThat(hits.getTotalHits(), equalTo(4L));
    SearchHit searchHit = hits.getAt(0);
    assertThat(searchHit.getId(), equalTo("1"));
    assertThat(searchHit.getNestedIdentity().getField().string(), equalTo("comments"));
    assertThat(searchHit.getNestedIdentity().getOffset(), equalTo(0));
    HighlightField highlightField = searchHit.getHighlightFields().get("comments.message");
    assertThat(highlightField.getFragments().length, equalTo(1));
    assertThat(highlightField.getFragments()[0].string(), equalTo("some <em>comment</em>"));
    // Can't explain nested hit with the main query, since both are in a different scopes, also the nested doc may not even have matched with the main query
    // If top_hits would have a query option then we can explain that query
    Explanation explanation = searchHit.getExplanation();
    assertFalse(explanation.isMatch());
    // Returns the version of the root document. Nested docs don't have a separate version
    long version = searchHit.getVersion();
    assertThat(version, equalTo(1L));
    assertThat(searchHit.getMatchedQueries(), arrayContaining("test"));
    SearchHitField field = searchHit.field("comments.user");
    assertThat(field.getValue().toString(), equalTo("a"));
    field = searchHit.field("script");
    assertThat(field.getValue().toString(), equalTo("5"));
    assertThat(searchHit.getSourceAsMap().size(), equalTo(1));
    assertThat(XContentMapValues.extractValue("comments.message", searchHit.getSourceAsMap()), equalTo("some comment"));
}
Also used : Script(org.elasticsearch.script.Script) SearchHit(org.elasticsearch.search.SearchHit) Explanation(org.apache.lucene.search.Explanation) Nested(org.elasticsearch.search.aggregations.bucket.nested.Nested) HighlightField(org.elasticsearch.search.fetch.subphase.highlight.HighlightField) Matchers.containsString(org.hamcrest.Matchers.containsString) SearchResponse(org.elasticsearch.action.search.SearchResponse) ElasticsearchAssertions.assertSearchResponse(org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchResponse) TopHits(org.elasticsearch.search.aggregations.metrics.tophits.TopHits) SearchHitField(org.elasticsearch.search.SearchHitField) SearchHits(org.elasticsearch.search.SearchHits) HighlightBuilder(org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder)

Example 2 with SearchHitField

use of org.elasticsearch.search.SearchHitField in project elasticsearch by elastic.

the class SearchFieldsIT method testScriptFieldsForNullReturn.

public void testScriptFieldsForNullReturn() throws Exception {
    client().prepareIndex("test", "type1", "1").setSource("foo", "bar").setRefreshPolicy("true").get();
    SearchResponse response = client().prepareSearch().setQuery(matchAllQuery()).addScriptField("test_script_1", new Script(ScriptType.INLINE, CustomScriptPlugin.NAME, "return null", Collections.emptyMap())).get();
    assertNoFailures(response);
    SearchHitField fieldObj = response.getHits().getAt(0).field("test_script_1");
    assertThat(fieldObj, notNullValue());
    List<?> fieldValues = fieldObj.getValues();
    assertThat(fieldValues, hasSize(1));
    assertThat(fieldValues.get(0), nullValue());
}
Also used : Script(org.elasticsearch.script.Script) SearchHitField(org.elasticsearch.search.SearchHitField) SearchResponse(org.elasticsearch.action.search.SearchResponse) ElasticsearchAssertions.assertSearchResponse(org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchResponse)

Example 3 with SearchHitField

use of org.elasticsearch.search.SearchHitField in project elasticsearch by elastic.

the class SearchFieldsIT method testScriptFields.

public void testScriptFields() throws Exception {
    assertAcked(prepareCreate("index").addMapping("type", "s", "type=keyword", "l", "type=long", "d", "type=double", "ms", "type=keyword", "ml", "type=long", "md", "type=double").get());
    final int numDocs = randomIntBetween(3, 8);
    List<IndexRequestBuilder> reqs = new ArrayList<>();
    for (int i = 0; i < numDocs; ++i) {
        reqs.add(client().prepareIndex("index", "type", Integer.toString(i)).setSource("s", Integer.toString(i), "ms", new String[] { Integer.toString(i), Integer.toString(i + 1) }, "l", i, "ml", new long[] { i, i + 1 }, "d", i, "md", new double[] { i, i + 1 }));
    }
    indexRandom(true, reqs);
    ensureSearchable();
    SearchRequestBuilder req = client().prepareSearch("index");
    for (String field : Arrays.asList("s", "ms", "l", "ml", "d", "md")) {
        req.addScriptField(field, new Script(ScriptType.INLINE, CustomScriptPlugin.NAME, "doc['" + field + "'].values", Collections.emptyMap()));
    }
    SearchResponse resp = req.get();
    assertSearchResponse(resp);
    for (SearchHit hit : resp.getHits().getHits()) {
        final int id = Integer.parseInt(hit.getId());
        Map<String, SearchHitField> fields = hit.getFields();
        assertThat(fields.get("s").getValues(), equalTo(Collections.<Object>singletonList(Integer.toString(id))));
        assertThat(fields.get("l").getValues(), equalTo(Collections.<Object>singletonList((long) id)));
        assertThat(fields.get("d").getValues(), equalTo(Collections.<Object>singletonList((double) id)));
        assertThat(fields.get("ms").getValues(), equalTo(Arrays.<Object>asList(Integer.toString(id), Integer.toString(id + 1))));
        assertThat(fields.get("ml").getValues(), equalTo(Arrays.<Object>asList((long) id, id + 1L)));
        assertThat(fields.get("md").getValues(), equalTo(Arrays.<Object>asList((double) id, id + 1d)));
    }
}
Also used : IndexRequestBuilder(org.elasticsearch.action.index.IndexRequestBuilder) Script(org.elasticsearch.script.Script) SearchRequestBuilder(org.elasticsearch.action.search.SearchRequestBuilder) SearchHit(org.elasticsearch.search.SearchHit) ArrayList(java.util.ArrayList) SearchHitField(org.elasticsearch.search.SearchHitField) Matchers.containsString(org.hamcrest.Matchers.containsString) SearchResponse(org.elasticsearch.action.search.SearchResponse) ElasticsearchAssertions.assertSearchResponse(org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchResponse)

Example 4 with SearchHitField

use of org.elasticsearch.search.SearchHitField in project elasticsearch by elastic.

the class FetchPhase method createSearchHit.

private SearchHit createSearchHit(SearchContext context, FieldsVisitor fieldsVisitor, int docId, int subDocId, LeafReaderContext subReaderContext) {
    if (fieldsVisitor == null) {
        return new SearchHit(docId);
    }
    loadStoredFields(context, subReaderContext, fieldsVisitor, subDocId);
    fieldsVisitor.postProcess(context.mapperService());
    Map<String, SearchHitField> searchFields = null;
    if (!fieldsVisitor.fields().isEmpty()) {
        searchFields = new HashMap<>(fieldsVisitor.fields().size());
        for (Map.Entry<String, List<Object>> entry : fieldsVisitor.fields().entrySet()) {
            searchFields.put(entry.getKey(), new SearchHitField(entry.getKey(), entry.getValue()));
        }
    }
    DocumentMapper documentMapper = context.mapperService().documentMapper(fieldsVisitor.uid().type());
    Text typeText;
    if (documentMapper == null) {
        typeText = new Text(fieldsVisitor.uid().type());
    } else {
        typeText = documentMapper.typeText();
    }
    SearchHit searchHit = new SearchHit(docId, fieldsVisitor.uid().id(), typeText, searchFields);
    // Set _source if requested.
    SourceLookup sourceLookup = context.lookup().source();
    sourceLookup.setSegmentAndDocument(subReaderContext, subDocId);
    if (fieldsVisitor.source() != null) {
        sourceLookup.setSource(fieldsVisitor.source());
    }
    return searchHit;
}
Also used : SourceLookup(org.elasticsearch.search.lookup.SourceLookup) SearchHit(org.elasticsearch.search.SearchHit) DocumentMapper(org.elasticsearch.index.mapper.DocumentMapper) SearchHitField(org.elasticsearch.search.SearchHitField) ArrayList(java.util.ArrayList) List(java.util.List) Text(org.elasticsearch.common.text.Text) HashMap(java.util.HashMap) Map(java.util.Map)

Example 5 with SearchHitField

use of org.elasticsearch.search.SearchHitField in project elasticsearch by elastic.

the class FetchPhase method createNestedSearchHit.

private SearchHit createNestedSearchHit(SearchContext context, int nestedTopDocId, int nestedSubDocId, int rootSubDocId, Set<String> fieldNames, List<String> fieldNamePatterns, LeafReaderContext subReaderContext) throws IOException {
    // Also if highlighting is requested on nested documents we need to fetch the _source from the root document,
    // otherwise highlighting will attempt to fetch the _source from the nested doc, which will fail,
    // because the entire _source is only stored with the root document.
    final FieldsVisitor rootFieldsVisitor = new FieldsVisitor(context.sourceRequested() || context.highlight() != null);
    loadStoredFields(context, subReaderContext, rootFieldsVisitor, rootSubDocId);
    rootFieldsVisitor.postProcess(context.mapperService());
    Map<String, SearchHitField> searchFields = getSearchFields(context, nestedSubDocId, fieldNames, fieldNamePatterns, subReaderContext);
    DocumentMapper documentMapper = context.mapperService().documentMapper(rootFieldsVisitor.uid().type());
    SourceLookup sourceLookup = context.lookup().source();
    sourceLookup.setSegmentAndDocument(subReaderContext, nestedSubDocId);
    ObjectMapper nestedObjectMapper = documentMapper.findNestedObjectMapper(nestedSubDocId, context, subReaderContext);
    assert nestedObjectMapper != null;
    SearchHit.NestedIdentity nestedIdentity = getInternalNestedIdentity(context, nestedSubDocId, subReaderContext, documentMapper, nestedObjectMapper);
    BytesReference source = rootFieldsVisitor.source();
    if (source != null) {
        Tuple<XContentType, Map<String, Object>> tuple = XContentHelper.convertToMap(source, true);
        Map<String, Object> sourceAsMap = tuple.v2();
        // Isolate the nested json array object that matches with nested hit and wrap it back into the same json
        // structure with the nested json array object being the actual content. The latter is important, so that
        // features like source filtering and highlighting work consistent regardless of whether the field points
        // to a json object array for consistency reasons on how we refer to fields
        Map<String, Object> nestedSourceAsMap = new HashMap<>();
        Map<String, Object> current = nestedSourceAsMap;
        for (SearchHit.NestedIdentity nested = nestedIdentity; nested != null; nested = nested.getChild()) {
            String nestedPath = nested.getField().string();
            current.put(nestedPath, new HashMap<>());
            Object extractedValue = XContentMapValues.extractValue(nestedPath, sourceAsMap);
            List<Map<String, Object>> nestedParsedSource;
            if (extractedValue instanceof List) {
                // nested field has an array value in the _source
                nestedParsedSource = (List<Map<String, Object>>) extractedValue;
            } else if (extractedValue instanceof Map) {
                // nested field has an object value in the _source. This just means the nested field has just one inner object, which is valid, but uncommon.
                nestedParsedSource = Collections.singletonList((Map<String, Object>) extractedValue);
            } else {
                throw new IllegalStateException("extracted source isn't an object or an array");
            }
            sourceAsMap = nestedParsedSource.get(nested.getOffset());
            if (nested.getChild() == null) {
                current.put(nestedPath, sourceAsMap);
            } else {
                Map<String, Object> next = new HashMap<>();
                current.put(nestedPath, next);
                current = next;
            }
        }
        context.lookup().source().setSource(nestedSourceAsMap);
        XContentType contentType = tuple.v1();
        BytesReference nestedSource = contentBuilder(contentType).map(sourceAsMap).bytes();
        context.lookup().source().setSource(nestedSource);
        context.lookup().source().setSourceContentType(contentType);
    }
    return new SearchHit(nestedTopDocId, rootFieldsVisitor.uid().id(), documentMapper.typeText(), nestedIdentity, searchFields);
}
Also used : BytesReference(org.elasticsearch.common.bytes.BytesReference) FieldsVisitor(org.elasticsearch.index.fieldvisitor.FieldsVisitor) CustomFieldsVisitor(org.elasticsearch.index.fieldvisitor.CustomFieldsVisitor) SourceLookup(org.elasticsearch.search.lookup.SourceLookup) SearchHit(org.elasticsearch.search.SearchHit) HashMap(java.util.HashMap) DocumentMapper(org.elasticsearch.index.mapper.DocumentMapper) XContentType(org.elasticsearch.common.xcontent.XContentType) SearchHitField(org.elasticsearch.search.SearchHitField) ArrayList(java.util.ArrayList) List(java.util.List) HashMap(java.util.HashMap) Map(java.util.Map) ObjectMapper(org.elasticsearch.index.mapper.ObjectMapper)

Aggregations

SearchHitField (org.elasticsearch.search.SearchHitField)23 SearchHit (org.elasticsearch.search.SearchHit)16 SearchResponse (org.elasticsearch.action.search.SearchResponse)12 SearchHits (org.elasticsearch.search.SearchHits)10 ArrayList (java.util.ArrayList)9 HashMap (java.util.HashMap)8 Map (java.util.Map)7 ElasticsearchAssertions.assertSearchResponse (org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchResponse)7 IOException (java.io.IOException)6 List (java.util.List)6 Text (org.elasticsearch.common.text.Text)6 SearchRequestBuilder (org.elasticsearch.action.search.SearchRequestBuilder)5 IndexRequestBuilder (org.elasticsearch.action.index.IndexRequestBuilder)4 InnerHitBuilder (org.elasticsearch.index.query.InnerHitBuilder)4 Script (org.elasticsearch.script.Script)4 CollapseBuilder (org.elasticsearch.search.collapse.CollapseBuilder)4 HighlightBuilder (org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder)4 QueryHelper (org.codelibs.fess.helper.QueryHelper)3 FessConfig (org.codelibs.fess.mylasta.direction.FessConfig)3 OptionalEntity (org.dbflute.optional.OptionalEntity)3