Phrase query with collate with Elastic Java Client 8.4

Hi Elastic Community,

I am looking to run a phrase suggestion with the collate parameter in the Elastic Java Client Version 8.4., but I can not get any working example running.

I currently encounter 2 problems:

  1. The collate.query.source parameter takes an argument of type String, which does not seem to work properly. I personally would've expected an argument of type Query. My strings seem to always break the API, but I guess with a working example this could be worked around.

  2. The response model PhraseSuggestOption seems to miss the collate_match field.

Can anyone help me with a working example please?

Thanks in advance.

Hi @Peter_Strasser

I made this example some time ago, I hope it helps you in some way.

  Map<String, FieldSuggester> map = new HashMap<>();
    map.put("simple_phrase", FieldSuggester.of(fs -> fs.phrase(
        PhraseSuggester.of(ps -> ps
            .field("title.trigram")
            .size(1)
            .directGenerator(DirectGenerator.of(dg -> dg.field("title.trigram").suggestMode(SuggestMode.Always).minWordLength(1)))
            .collate(PhraseSuggestCollate.of(
                c -> c.query(PhraseSuggestCollateQuery.of(psq -> psq
                    .source("{\"match\": {\"{{field_name}}\" : \"{{suggestion}}\"}}")))
                    .params(Map.of("field_name", JsonData.of("title")))
            ))
        )
        )
    ));
    Suggester suggester = Suggester.of(s -> s
        .suggesters(map)
        .text("noble prize")
    );
1 Like

Hi @RabBit_BR ,

thanks for your help. I converted your code to kotlin and the query ran through.
I had to add the highlight option, because the client treats it as a required field, but that's another issue I guess.

This code prints the suggestion for "noble price", as expected. But I can not find the information, of collate_match is true or false for the response anywhere. Am I using the correct models? I am casting the type with suggestion.phrase() into a "PhraseSuggest".


val simplePhrase = "simple_phrase"
val map = mapOf<String, FieldSuggester>(
    simplePhrase to
            FieldSuggester.of { fs ->
                fs.phrase(
                    PhraseSuggester.of { ps ->
                        ps
                            .field("title.trigram")
                            .size(1)
                            .highlight { h ->
                                h.preTag("<em>")
                                h.postTag("</em>")
                            }
                            .directGenerator(DirectGenerator.of { dg ->
                                dg.field("title.trigram").suggestMode(SuggestMode.Always).minWordLength(1)
                            })
                            .collate(PhraseSuggestCollate.of { c ->
                                c.query(PhraseSuggestCollateQuery.of { psq ->
                                    psq.source("{\"match\": {\"{{field_name}}\" : \"{{suggestion}}\"}}")
                                }).params(mapOf("field_name" to JsonData.of("title")))
                            })
                    }
                )
            })

val suggester: Suggester = Suggester.of { s ->
    s.suggesters(map)
        .text("noble price")
}

val suggestResponse = esClient.search(SearchRequest.of { sr ->
    sr
        .index(indexName)
        .suggest(suggester)
}, Any::class.java).asDeferred().await()

val suggestion = suggestResponse.suggest()[simplePhrase]?.getOrNull(0) ?: throw IllegalStateException("")

suggestion.phrase().options().forEach { phraseSuggestionOption ->
    println(phraseSuggestionOption.text())
    println(phraseSuggestionOption.highlighted())
    println(phraseSuggestionOption.score())
    // how do I get collate_match information?
}

Add prune = true

PhraseSuggestCollate.of(
                c -> c.query(PhraseSuggestCollateQuery.of(psq -> psq
                    .source("{\"match\": {\"{{field_name}}\" : \"{{suggestion}}\"}}")))
                    .params(Map.of("field_name", JsonData.of("title")))
                    .prune(true)

Documentation:

Additionally, you can specify a prune to control if all phrase suggestions will be returned; when set to true the suggestions will have an additional option collate_match , which will be true if matching documents for the phrase was found, false otherwise. The default value for prune is false .

You are right I missed this in the query, thank you.

I am still unsure on how to access this flag from the code after adding this flag. How do I cast it to a model where the collate_match is included?

Are these lines wrong?

val suggestion = suggestResponse.suggest()[simplePhrase]?.getOrNull(0) ?: throw IllegalStateException("")

suggestion.phrase().options().forEach { phraseSuggestionOption ->
    println(phraseSuggestionOption.text())
    println(phraseSuggestionOption.highlighted())
    println(phraseSuggestionOption.score())
    // how do I get collate_match information?
}

It looks like the new java api lost this field. In these cases I open an issue in GIT and wait for the fix.

I created an issue in the GitHub repo, thank you very much for your help. :slight_smile:

PhraseSuggestOption missing collate_match field · Issue #411 · elastic/elasticsearch-java (github.com)

1 Like

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.