Search in sources :

Example 11 with ContextMapping

use of org.elasticsearch.search.suggest.completion.context.ContextMapping in project elasticsearch by elastic.

the class CompletionFieldMapper method parse.

/**
     * Acceptable inputs:
     *  "STRING" - interpreted as the field value (input)
     *  "OBJECT" - { "input": STRING|ARRAY, "weight": STRING|INT, "contexts": ARRAY|OBJECT }
     */
private void parse(ParseContext parseContext, Token token, XContentParser parser, Map<String, CompletionInputMetaData> inputMap) throws IOException {
    String currentFieldName = null;
    if (token == Token.VALUE_STRING) {
        inputMap.put(parser.text(), new CompletionInputMetaData(Collections.<String, Set<CharSequence>>emptyMap(), 1));
    } else if (token == Token.START_OBJECT) {
        Set<String> inputs = new HashSet<>();
        int weight = 1;
        Map<String, Set<CharSequence>> contextsMap = new HashMap<>();
        while ((token = parser.nextToken()) != Token.END_OBJECT) {
            if (token == Token.FIELD_NAME) {
                currentFieldName = parser.currentName();
                if (!ALLOWED_CONTENT_FIELD_NAMES.contains(currentFieldName)) {
                    throw new IllegalArgumentException("unknown field name [" + currentFieldName + "], must be one of " + ALLOWED_CONTENT_FIELD_NAMES);
                }
            } else if (currentFieldName != null) {
                if (Fields.CONTENT_FIELD_NAME_INPUT.equals(currentFieldName)) {
                    if (token == Token.VALUE_STRING) {
                        inputs.add(parser.text());
                    } else if (token == Token.START_ARRAY) {
                        while ((token = parser.nextToken()) != Token.END_ARRAY) {
                            if (token == Token.VALUE_STRING) {
                                inputs.add(parser.text());
                            } else {
                                throw new IllegalArgumentException("input array must have string values, but was [" + token.name() + "]");
                            }
                        }
                    } else {
                        throw new IllegalArgumentException("input must be a string or array, but was [" + token.name() + "]");
                    }
                } else if (Fields.CONTENT_FIELD_NAME_WEIGHT.equals(currentFieldName)) {
                    final Number weightValue;
                    if (token == Token.VALUE_STRING) {
                        try {
                            weightValue = Long.parseLong(parser.text());
                        } catch (NumberFormatException e) {
                            throw new IllegalArgumentException("weight must be an integer, but was [" + parser.text() + "]");
                        }
                    } else if (token == Token.VALUE_NUMBER) {
                        NumberType numberType = parser.numberType();
                        if (NumberType.LONG != numberType && NumberType.INT != numberType) {
                            throw new IllegalArgumentException("weight must be an integer, but was [" + parser.numberValue() + "]");
                        }
                        weightValue = parser.numberValue();
                    } else {
                        throw new IllegalArgumentException("weight must be a number or string, but was [" + token.name() + "]");
                    }
                    if (weightValue.longValue() < 0 || weightValue.longValue() > Integer.MAX_VALUE) {
                        // always parse a long to make sure we don't get overflow
                        throw new IllegalArgumentException("weight must be in the interval [0..2147483647], but was [" + weightValue.longValue() + "]");
                    }
                    weight = weightValue.intValue();
                } else if (Fields.CONTENT_FIELD_NAME_CONTEXTS.equals(currentFieldName)) {
                    if (fieldType().hasContextMappings() == false) {
                        throw new IllegalArgumentException("contexts field is not supported for field: [" + fieldType().name() + "]");
                    }
                    ContextMappings contextMappings = fieldType().getContextMappings();
                    XContentParser.Token currentToken = parser.currentToken();
                    if (currentToken == XContentParser.Token.START_OBJECT) {
                        ContextMapping contextMapping = null;
                        String fieldName = null;
                        while ((currentToken = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
                            if (currentToken == XContentParser.Token.FIELD_NAME) {
                                fieldName = parser.currentName();
                                contextMapping = contextMappings.get(fieldName);
                            } else if (currentToken == XContentParser.Token.VALUE_STRING || currentToken == XContentParser.Token.START_ARRAY || currentToken == XContentParser.Token.START_OBJECT) {
                                assert fieldName != null;
                                assert !contextsMap.containsKey(fieldName);
                                contextsMap.put(fieldName, contextMapping.parseContext(parseContext, parser));
                            } else {
                                throw new IllegalArgumentException("contexts must be an object or an array , but was [" + currentToken + "]");
                            }
                        }
                    } else {
                        throw new IllegalArgumentException("contexts must be an object or an array , but was [" + currentToken + "]");
                    }
                }
            }
        }
        for (String input : inputs) {
            if (inputMap.containsKey(input) == false || inputMap.get(input).weight < weight) {
                inputMap.put(input, new CompletionInputMetaData(contextsMap, weight));
            }
        }
    } else {
        throw new ElasticsearchParseException("failed to parse expected text or object got" + token.name());
    }
}
Also used : HashSet(java.util.HashSet) Set(java.util.Set) ContextMappings(org.elasticsearch.search.suggest.completion.context.ContextMappings) Token(org.elasticsearch.common.xcontent.XContentParser.Token) NumberType(org.elasticsearch.common.xcontent.XContentParser.NumberType) ContextMapping(org.elasticsearch.search.suggest.completion.context.ContextMapping) ElasticsearchParseException(org.elasticsearch.ElasticsearchParseException) HashMap(java.util.HashMap) Map(java.util.Map) XContentParser(org.elasticsearch.common.xcontent.XContentParser)

Example 12 with ContextMapping

use of org.elasticsearch.search.suggest.completion.context.ContextMapping in project elasticsearch by elastic.

the class CompletionSuggestionBuilder method build.

@Override
public SuggestionContext build(QueryShardContext context) throws IOException {
    CompletionSuggestionContext suggestionContext = new CompletionSuggestionContext(context);
    // copy over common settings to each suggestion builder
    final MapperService mapperService = context.getMapperService();
    populateCommonFields(mapperService, suggestionContext);
    suggestionContext.setFuzzyOptions(fuzzyOptions);
    suggestionContext.setRegexOptions(regexOptions);
    MappedFieldType mappedFieldType = mapperService.fullName(suggestionContext.getField());
    if (mappedFieldType == null || mappedFieldType instanceof CompletionFieldMapper.CompletionFieldType == false) {
        throw new IllegalArgumentException("Field [" + suggestionContext.getField() + "] is not a completion suggest field");
    }
    if (mappedFieldType instanceof CompletionFieldMapper.CompletionFieldType) {
        CompletionFieldMapper.CompletionFieldType type = (CompletionFieldMapper.CompletionFieldType) mappedFieldType;
        suggestionContext.setFieldType(type);
        if (type.hasContextMappings() && contextBytes != null) {
            try (XContentParser contextParser = XContentFactory.xContent(contextBytes).createParser(context.getXContentRegistry(), contextBytes)) {
                if (type.hasContextMappings() && contextParser != null) {
                    ContextMappings contextMappings = type.getContextMappings();
                    contextParser.nextToken();
                    Map<String, List<ContextMapping.InternalQueryContext>> queryContexts = new HashMap<>(contextMappings.size());
                    assert contextParser.currentToken() == XContentParser.Token.START_OBJECT;
                    XContentParser.Token currentToken;
                    String currentFieldName;
                    while ((currentToken = contextParser.nextToken()) != XContentParser.Token.END_OBJECT) {
                        if (currentToken == XContentParser.Token.FIELD_NAME) {
                            currentFieldName = contextParser.currentName();
                            final ContextMapping mapping = contextMappings.get(currentFieldName);
                            queryContexts.put(currentFieldName, mapping.parseQueryContext(context.newParseContext(contextParser)));
                        }
                    }
                    suggestionContext.setQueryContexts(queryContexts);
                }
            }
        } else if (contextBytes != null) {
            throw new IllegalArgumentException("suggester [" + type.name() + "] doesn't expect any context");
        }
    }
    assert suggestionContext.getFieldType() != null : "no completion field type set";
    return suggestionContext;
}
Also used : HashMap(java.util.HashMap) CompletionFieldMapper(org.elasticsearch.index.mapper.CompletionFieldMapper) ContextMappings(org.elasticsearch.search.suggest.completion.context.ContextMappings) ContextMapping(org.elasticsearch.search.suggest.completion.context.ContextMapping) MappedFieldType(org.elasticsearch.index.mapper.MappedFieldType) List(java.util.List) MapperService(org.elasticsearch.index.mapper.MapperService) XContentParser(org.elasticsearch.common.xcontent.XContentParser)

Example 13 with ContextMapping

use of org.elasticsearch.search.suggest.completion.context.ContextMapping in project elasticsearch by elastic.

the class ContextCompletionSuggestSearchIT method testSingleContextMultipleContexts.

public void testSingleContextMultipleContexts() throws Exception {
    CategoryContextMapping contextMapping = ContextBuilder.category("cat").field("cat").build();
    LinkedHashMap<String, ContextMapping> map = new LinkedHashMap<String, ContextMapping>(Collections.singletonMap("cat", contextMapping));
    final CompletionMappingBuilder mapping = new CompletionMappingBuilder().context(map);
    createIndexAndMapping(mapping);
    int numDocs = 10;
    List<String> contexts = Arrays.asList("type1", "type2", "type3", "type4");
    List<IndexRequestBuilder> indexRequestBuilders = new ArrayList<>();
    for (int i = 0; i < numDocs; i++) {
        XContentBuilder source = jsonBuilder().startObject().startObject(FIELD).field("input", "suggestion" + i).field("weight", i + 1).endObject().field("cat", contexts).endObject();
        indexRequestBuilders.add(client().prepareIndex(INDEX, TYPE, "" + i).setSource(source));
    }
    indexRandom(true, indexRequestBuilders);
    CompletionSuggestionBuilder prefix = SuggestBuilders.completionSuggestion(FIELD).prefix("sugg");
    assertSuggestions("foo", prefix, "suggestion9", "suggestion8", "suggestion7", "suggestion6", "suggestion5");
}
Also used : ArrayList(java.util.ArrayList) GeoPoint(org.elasticsearch.common.geo.GeoPoint) CategoryContextMapping(org.elasticsearch.search.suggest.completion.context.CategoryContextMapping) LinkedHashMap(java.util.LinkedHashMap) IndexRequestBuilder(org.elasticsearch.action.index.IndexRequestBuilder) CompletionSuggestionBuilder(org.elasticsearch.search.suggest.completion.CompletionSuggestionBuilder) GeoContextMapping(org.elasticsearch.search.suggest.completion.context.GeoContextMapping) ContextMapping(org.elasticsearch.search.suggest.completion.context.ContextMapping) CategoryContextMapping(org.elasticsearch.search.suggest.completion.context.CategoryContextMapping) CompletionMappingBuilder(org.elasticsearch.search.suggest.CompletionSuggestSearchIT.CompletionMappingBuilder) XContentBuilder(org.elasticsearch.common.xcontent.XContentBuilder)

Example 14 with ContextMapping

use of org.elasticsearch.search.suggest.completion.context.ContextMapping in project elasticsearch by elastic.

the class ContextCompletionSuggestSearchIT method testSingleContextBoosting.

public void testSingleContextBoosting() throws Exception {
    CategoryContextMapping contextMapping = ContextBuilder.category("cat").field("cat").build();
    LinkedHashMap<String, ContextMapping> map = new LinkedHashMap<String, ContextMapping>(Collections.singletonMap("cat", contextMapping));
    final CompletionMappingBuilder mapping = new CompletionMappingBuilder().context(map);
    createIndexAndMapping(mapping);
    int numDocs = 10;
    List<IndexRequestBuilder> indexRequestBuilders = new ArrayList<>();
    for (int i = 0; i < numDocs; i++) {
        indexRequestBuilders.add(client().prepareIndex(INDEX, TYPE, "" + i).setSource(jsonBuilder().startObject().startObject(FIELD).field("input", "suggestion" + i).field("weight", i + 1).endObject().field("cat", "cat" + i % 2).endObject()));
    }
    indexRandom(true, indexRequestBuilders);
    CompletionSuggestionBuilder prefix = SuggestBuilders.completionSuggestion(FIELD).prefix("sugg").contexts(Collections.singletonMap("cat", Arrays.asList(CategoryQueryContext.builder().setCategory("cat0").setBoost(3).build(), CategoryQueryContext.builder().setCategory("cat1").build())));
    assertSuggestions("foo", prefix, "suggestion8", "suggestion6", "suggestion4", "suggestion9", "suggestion2");
}
Also used : IndexRequestBuilder(org.elasticsearch.action.index.IndexRequestBuilder) CompletionSuggestionBuilder(org.elasticsearch.search.suggest.completion.CompletionSuggestionBuilder) GeoContextMapping(org.elasticsearch.search.suggest.completion.context.GeoContextMapping) ContextMapping(org.elasticsearch.search.suggest.completion.context.ContextMapping) CategoryContextMapping(org.elasticsearch.search.suggest.completion.context.CategoryContextMapping) ArrayList(java.util.ArrayList) CompletionMappingBuilder(org.elasticsearch.search.suggest.CompletionSuggestSearchIT.CompletionMappingBuilder) GeoPoint(org.elasticsearch.common.geo.GeoPoint) CategoryContextMapping(org.elasticsearch.search.suggest.completion.context.CategoryContextMapping) LinkedHashMap(java.util.LinkedHashMap)

Example 15 with ContextMapping

use of org.elasticsearch.search.suggest.completion.context.ContextMapping in project elasticsearch by elastic.

the class ContextCompletionSuggestSearchIT method testMultiContextBoosting.

@AwaitsFix(bugUrl = "multiple context boosting is broken, as a suggestion, contexts pair is treated as (num(context) entries)")
public void testMultiContextBoosting() throws Exception {
    LinkedHashMap<String, ContextMapping> map = new LinkedHashMap<>();
    map.put("cat", ContextBuilder.category("cat").field("cat").build());
    map.put("type", ContextBuilder.category("type").field("type").build());
    final CompletionMappingBuilder mapping = new CompletionMappingBuilder().context(map);
    createIndexAndMapping(mapping);
    int numDocs = 10;
    List<IndexRequestBuilder> indexRequestBuilders = new ArrayList<>();
    for (int i = 0; i < numDocs; i++) {
        XContentBuilder source = jsonBuilder().startObject().startObject(FIELD).field("input", "suggestion" + i).field("weight", i + 1).endObject().field("cat", "cat" + i % 2).field("type", "type" + i % 4).endObject();
        indexRequestBuilders.add(client().prepareIndex(INDEX, TYPE, "" + i).setSource(source));
    }
    indexRandom(true, indexRequestBuilders);
    // boost only on context cat
    CompletionSuggestionBuilder catBoostSuggest = SuggestBuilders.completionSuggestion(FIELD).prefix("sugg");
    catBoostSuggest.contexts(Collections.singletonMap("cat", Arrays.asList(CategoryQueryContext.builder().setCategory("cat0").setBoost(3).build(), CategoryQueryContext.builder().setCategory("cat1").build())));
    assertSuggestions("foo", catBoostSuggest, "suggestion8", "suggestion6", "suggestion4", "suggestion9", "suggestion2");
    // boost only on context type
    CompletionSuggestionBuilder typeBoostSuggest = SuggestBuilders.completionSuggestion(FIELD).prefix("sugg");
    typeBoostSuggest.contexts(Collections.singletonMap("type", Arrays.asList(CategoryQueryContext.builder().setCategory("type2").setBoost(2).build(), CategoryQueryContext.builder().setCategory("type1").setBoost(4).build())));
    assertSuggestions("foo", typeBoostSuggest, "suggestion9", "suggestion5", "suggestion6", "suggestion1", "suggestion2");
    // boost on both contexts
    CompletionSuggestionBuilder multiContextBoostSuggest = SuggestBuilders.completionSuggestion(FIELD).prefix("sugg");
    // query context order should never matter
    Map<String, List<? extends ToXContent>> contextMap = new HashMap<>();
    contextMap.put("type", Arrays.asList(CategoryQueryContext.builder().setCategory("type2").setBoost(2).build(), CategoryQueryContext.builder().setCategory("type1").setBoost(4).build()));
    contextMap.put("cat", Arrays.asList(CategoryQueryContext.builder().setCategory("cat0").setBoost(3).build(), CategoryQueryContext.builder().setCategory("cat1").build()));
    multiContextBoostSuggest.contexts(contextMap);
    assertSuggestions("foo", multiContextBoostSuggest, "suggestion9", "suggestion6", "suggestion5", "suggestion2", "suggestion1");
}
Also used : ToXContent(org.elasticsearch.common.xcontent.ToXContent) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) ArrayList(java.util.ArrayList) GeoPoint(org.elasticsearch.common.geo.GeoPoint) LinkedHashMap(java.util.LinkedHashMap) IndexRequestBuilder(org.elasticsearch.action.index.IndexRequestBuilder) CompletionSuggestionBuilder(org.elasticsearch.search.suggest.completion.CompletionSuggestionBuilder) GeoContextMapping(org.elasticsearch.search.suggest.completion.context.GeoContextMapping) ContextMapping(org.elasticsearch.search.suggest.completion.context.ContextMapping) CategoryContextMapping(org.elasticsearch.search.suggest.completion.context.CategoryContextMapping) CompletionMappingBuilder(org.elasticsearch.search.suggest.CompletionSuggestSearchIT.CompletionMappingBuilder) ArrayList(java.util.ArrayList) List(java.util.List) XContentBuilder(org.elasticsearch.common.xcontent.XContentBuilder)

Aggregations

ContextMapping (org.elasticsearch.search.suggest.completion.context.ContextMapping)20 LinkedHashMap (java.util.LinkedHashMap)18 CategoryContextMapping (org.elasticsearch.search.suggest.completion.context.CategoryContextMapping)18 GeoContextMapping (org.elasticsearch.search.suggest.completion.context.GeoContextMapping)18 CompletionMappingBuilder (org.elasticsearch.search.suggest.CompletionSuggestSearchIT.CompletionMappingBuilder)16 CompletionSuggestionBuilder (org.elasticsearch.search.suggest.completion.CompletionSuggestionBuilder)16 ArrayList (java.util.ArrayList)15 IndexRequestBuilder (org.elasticsearch.action.index.IndexRequestBuilder)15 GeoPoint (org.elasticsearch.common.geo.GeoPoint)15 XContentBuilder (org.elasticsearch.common.xcontent.XContentBuilder)15 HashMap (java.util.HashMap)5 List (java.util.List)3 Map (java.util.Map)3 ToXContent (org.elasticsearch.common.xcontent.ToXContent)2 XContentParser (org.elasticsearch.common.xcontent.XContentParser)2 ContextMappings (org.elasticsearch.search.suggest.completion.context.ContextMappings)2 HashSet (java.util.HashSet)1 Set (java.util.Set)1 ElasticsearchParseException (org.elasticsearch.ElasticsearchParseException)1 IndexResponse (org.elasticsearch.action.index.IndexResponse)1