Skip to content

MLT JsonSerializationException : Could not create an instance of type Nest.IMultiGetOperation. Type is an interface or abstract class and cannot be instantiated. Path 'query.mlt.docs[0]._index' #1415

@abibell

Description

@abibell

Scenario

Elastic's More like this is good to find related documents for a documentId. As a business user I cannot know which fields make results relevant. It could be fields A, B & C today. I may realise that X & Y should be added when I am in production due to customer issues. What I want is that the way to configure the fields. In developer terms, a developer should be able to change the MLT query in a configuration and the system should use the query as template. In order to do this I should be able to serialise/deserialise MLT queries.

Working sense query

POST _search
{
   "query": {
      "mlt": {
         "fields": [
            "name", "content"
         ],
         "docs": [
            {
               "_index": "my_index",
               "_type": "my_type",
               "_id": "SOME_ID"
            }
         ],
         "min_term_freq": 1,
         "max_query_terms": 12         
      }
   },
   "size": 2
}

{
   "query": {
      "more_like_this": {
         "fields": [
            "title",
            "description",
            "abstract",
            "subject",
            "source"
         ],
         "min_term_freq": 1,
         "max_query_terms": 12,

      }
   },
   "size": 2
}

Test code that fails in MoreLikeThisQueryJson.cs

[Test]
public void TestMoreLikeThisQuery()
{
    Func<MoreLikeThisQueryDocumentsDescriptor<dynamic>, MoreLikeThisQueryDocumentsDescriptor<dynamic>> documentsSelector = d => d.Get("SOME_ID", op => op.Index("my_index").Type("my_type"));
    Action<MoreLikeThisQueryDescriptor<ElasticsearchProject>> selector = fz => fz
        .Name("named_query")
        .OnFields(f => f.Name, f => f.Content)
        .LikeText("elasticsearcc")
        .Documents(documentsSelector)//This causes the error
        .MinTermFrequency(1)
        .MaxQueryTerms(12);
    var s = new SearchDescriptor<ElasticsearchProject>()
        .From(0)
        .Size(10)
        .Query(q => q.MoreLikeThis(selector));

    var json = TestElasticClient.Serialize(s);
    const string expected = @"{ from: 0, size: 10, query : 
    { mlt: { 
        _name: ""named_query"",
        fields : [""name"", ""content"" ],
        like_text : ""elasticsearcc"" ,
        ""docs"": [
                    {
                       ""_index"": ""my_index"",
                       ""_type"": ""my_type"",
                       ""_id"": ""SOME_ID""
                    }
                 ],
         ""min_term_freq"": 1,
         ""max_query_terms"": 12
    }}}";
    Verify<SearchDescriptor<dynamic>>(json, expected);
}

private static void Verify<T>(string json, string expected) where T: class
{
    Assert.True(json.JsonEquals(expected), json);
    var returnedJson = TestElasticClient.Serialize(TestElasticClient.Deserialize<T>(json));
    Assert.True(json.JsonEquals(returnedJson), json);
}

Further Investigation lead to Conclusions

If we replace
Assert.True(json.JsonEquals(expected), json);
with
Verify<MoreLikeThisQueryDescriptor<ElasticsearchProject>>(json, expected);
in MoreLikeThisQueryJson.cs we get more test case failures.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions