elasticsearch-net icon indicating copy to clipboard operation
elasticsearch-net copied to clipboard

Unable to use descriptors to set Fields in MultiMatchQueryDescriptor query

Open ashitanojoe opened this issue 1 year ago • 6 comments

Is your feature request related to a problem? Please describe. When trying to migrate our Nest code to the new client I ran into a problem migrating a Multimatch query. In Nest, we could use descriptors to set with fields the multimatch should use for the query. This is not available in the new client, forcing me to use magic strings.

Here is the MultiMatch portion of the query using the new client, with the Nest code commented out.

.MultiMatch(mm => mm
    .Type(TextQueryType.BestFields)
    .Fields(new[]
    {
        "name.lownerngram",
        "tags.lowerekeyword"
    })
    //.Fields(fds => fds
    //    .Field(f => f.Name.Suffix("lowerngram"))
    //    .Field(f => f.Tags.Suffix("lowerkeyword"))
    //)
    .Query(queryString)
)

Describe the solution you'd like Would like to use descriptors to set the fields the multimatch query will use in a way similar to the commented out code.

ashitanojoe avatar Jan 17 '24 09:01 ashitanojoe

Hi @ashitanojoe ,

This is one of the features I definitely plan to bring back. I sadly can't give you an ETA.

As a workaround, the Field type can be constructed like this:

Field<TDocument>(f => f.Name)

which allows for:

.MultiMatch(mm => mm
    .Type(TextQueryType.BestFields)
    .Fields(new[]
    {
        Field<TDocument>(f => f.Name),
        Field<TDocument>(f => f.Tags)
    })
    .Query(queryString)
)

I'm not sure, if .Suffix() is implemented already, but you could create your own extension method for the Field class in order to support this functionality, if it's not yet implemented.

flobernd avatar Jan 17 '24 13:01 flobernd

Hi @flobernd ,

Thank you for pointing out the workaround. Not sure how I missed that. I definitely like that better than passing a string.

ashitanojoe avatar Jan 26 '24 00:01 ashitanojoe

I found this issue when trying to migrate some QueryString queries in 8.15.x and I was struggling to find any examples that didn't use magic strings for Fields. I'm sorry if I'm being obtuse but I can't find any generic constructor in the style of Field<TDocument>(f => f.Name) so is this workaround no longer correct?

braveyp avatar Aug 22 '24 16:08 braveyp

I couldn't get the suggested workaround to work either, so I ended up using magic strings.

ashitanojoe avatar Aug 22 '24 22:08 ashitanojoe

Hi @braveyp @ashitanojoe,

I'm very sorry about the wrong syntax example I've provided. The correct syntax is as follows:

var response = await client.SearchAsync<Person>(r => r
    .Index("person")
    .Query(q => q
        .QueryString(qs => qs
            .Fields(new Expression<Func<Person, object>>[]
            {
                f => f.Age!,
                f => f.FirstName!
            })
        )
    )
);

The Fields type has an implicit conversion operator from Expression[]:

public static implicit operator Fields?(Expression[]? expressions)

To make use of this, it's required to explicitly declare the type of the array parameter (new Expression<Func<Person, object>>[]) like shown above.

The NEST syntax from the initial post is not going to be re-introduced:

.Fields(fds => fds
    .Field(f => f.Name.Suffix("lowerngram"))
    .Field(f => f.Tags.Suffix("lowerkeyword"))
)

But, my plan is to change the code generator in a way that it generates this overload:

public QueryStringQueryDescriptor<TDocument> Fields(params Expression<Func<TDocument, object>> fields)

in addition to the current:

public QueryStringQueryDescriptor<TDocument> Fields(Elastic.Clients.Elasticsearch.Fields? fields)

This will then allow to pass an array of Expression without explicitly having to define the expression type:

var response = await client.SearchAsync<Person>(r => r
    .Index("person")
    .Query(q => q
        .QueryString(qs => qs
            .Fields(
                f => f.Age!,
                f => f.FirstName!
            )
        )
    )
);

flobernd avatar Aug 23 '24 08:08 flobernd

Thanks for the help, that works perfectly.

braveyp avatar Aug 23 '24 08:08 braveyp