Search in sources :

Example 1 with ContextMappings

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

the class CompletionSuggestionContext method toQuery.

CompletionQuery toQuery() {
    CompletionFieldMapper.CompletionFieldType fieldType = getFieldType();
    final CompletionQuery query;
    if (getPrefix() != null) {
        query = createCompletionQuery(getPrefix(), fieldType);
    } else if (getRegex() != null) {
        if (fuzzyOptions != null) {
            throw new IllegalArgumentException("can not use 'fuzzy' options with 'regex");
        }
        if (regexOptions == null) {
            regexOptions = RegexOptions.builder().build();
        }
        query = fieldType.regexpQuery(getRegex(), regexOptions.getFlagsValue(), regexOptions.getMaxDeterminizedStates());
    } else if (getText() != null) {
        query = createCompletionQuery(getText(), fieldType);
    } else {
        throw new IllegalArgumentException("'prefix/text' or 'regex' must be defined");
    }
    if (fieldType.hasContextMappings()) {
        ContextMappings contextMappings = fieldType.getContextMappings();
        return contextMappings.toContextQuery(query, queryContexts);
    }
    return query;
}
Also used : CompletionFieldMapper(org.elasticsearch.index.mapper.CompletionFieldMapper) ContextMappings(org.elasticsearch.search.suggest.completion.context.ContextMappings) CompletionQuery(org.apache.lucene.search.suggest.document.CompletionQuery)

Example 2 with ContextMappings

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

the class CompletionFieldTypeTests method setupProperties.

@Before
public void setupProperties() {
    addModifier(new Modifier("preserve_separators", false) {

        @Override
        public void modify(MappedFieldType ft) {
            CompletionFieldMapper.CompletionFieldType cft = (CompletionFieldMapper.CompletionFieldType) ft;
            cft.setPreserveSep(false);
        }
    });
    addModifier(new Modifier("preserve_position_increments", false) {

        @Override
        public void modify(MappedFieldType ft) {
            CompletionFieldMapper.CompletionFieldType cft = (CompletionFieldMapper.CompletionFieldType) ft;
            cft.setPreservePositionIncrements(false);
        }
    });
    addModifier(new Modifier("context_mappings", false) {

        @Override
        public void modify(MappedFieldType ft) {
            CompletionFieldMapper.CompletionFieldType cft = (CompletionFieldMapper.CompletionFieldType) ft;
            ContextMappings contextMappings = new ContextMappings(Arrays.asList(ContextBuilder.category("foo").build(), ContextBuilder.geo("geo").build()));
            cft.setContextMappings(contextMappings);
        }
    });
}
Also used : CompletionFieldMapper(org.elasticsearch.index.mapper.CompletionFieldMapper) MappedFieldType(org.elasticsearch.index.mapper.MappedFieldType) ContextMappings(org.elasticsearch.search.suggest.completion.context.ContextMappings) Before(org.junit.Before)

Example 3 with ContextMappings

use of org.elasticsearch.search.suggest.completion.context.ContextMappings 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 4 with ContextMappings

use of org.elasticsearch.search.suggest.completion.context.ContextMappings 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)

Aggregations

ContextMappings (org.elasticsearch.search.suggest.completion.context.ContextMappings)4 CompletionFieldMapper (org.elasticsearch.index.mapper.CompletionFieldMapper)3 HashMap (java.util.HashMap)2 XContentParser (org.elasticsearch.common.xcontent.XContentParser)2 MappedFieldType (org.elasticsearch.index.mapper.MappedFieldType)2 ContextMapping (org.elasticsearch.search.suggest.completion.context.ContextMapping)2 HashSet (java.util.HashSet)1 List (java.util.List)1 Map (java.util.Map)1 Set (java.util.Set)1 CompletionQuery (org.apache.lucene.search.suggest.document.CompletionQuery)1 ElasticsearchParseException (org.elasticsearch.ElasticsearchParseException)1 NumberType (org.elasticsearch.common.xcontent.XContentParser.NumberType)1 Token (org.elasticsearch.common.xcontent.XContentParser.Token)1 MapperService (org.elasticsearch.index.mapper.MapperService)1 Before (org.junit.Before)1