ElasticSearch NEST term query returns no results

泪湿孤枕 提交于 2019-12-24 04:32:57

问题


Here my schema

[ElasticType(Name = "importFile")]
public class ImportFile : DocumentMapping
{
    [ElasticProperty(Store = false, Index = FieldIndexOption.NotAnalyzed)]
    public string FileName { get; set; }

    [ElasticProperty(Store = false, Index = FieldIndexOption.NotAnalyzed)]
    public string GroupId { get; set; }

    [ElasticProperty(Store = false, Index = FieldIndexOption.Analyzed)]
    public string FilePath { get; set; }
}

I made a NEST query like this one:

    var res = ElasticClient.Search<ImportFile>(s => s
        .Index(ElasticIndexName)
        .Filter(f =>
            f.Term(t => t.FileName, "Group-1.uhh"))).Documents.ToArray();

and returns zero elements!

If I peek inside the db (using postman) I can see my documents:

{
  "took": 5,
  "timed_out": false,
  "_shards": {
    "total": 2,
    "successful": 2,
    "failed": 0
  },
  "hits": {
    "total": 2,
    "max_score": 14.069489,
    "hits": [
      {
        "_index": "reviewer-bdd-test-index",
        "_type": "importFile",
        "_id": "AU9kUka2hr5Jg98UXOae",
        "_score": 14.069489,
        "_source": {
          "fileName": "Group-1.uhh",
          "groupId": "0ae1206d0644eabd82ae490e612732df5da2cd141fdee70dc64207f86c96094f",
          "filePath": ""
        }
      },
      {
        "_index": "reviewer-bdd-test-index",
        "_type": "importFile",
        "_id": "AU9kZO25hr5Jg98UXRnk",
        "_score": 14.069489,
        "_source": {
          "fileName": "group-1.uhh",
          "groupId": "0ae1206d0644eabd82ae490e612732df5da2cd141fdee70dc64207f86c96094f",
          "filePath": ""
        }
      }
    ]
  }
}

回答1:


It sounds like you may not have explicitly put a mapping for the type into the index before indexing your documents, so Elasticsearch has inferred the mapping based on the default mappings for fields in the documents it has seen. As an example, given the following type

[ElasticType(Name = "importFile")]
public class ImportFile
{
    [ElasticProperty(Store = false, Index = FieldIndexOption.NotAnalyzed)]
    public string FileName { get; set; }

    [ElasticProperty(Store = false, Index = FieldIndexOption.NotAnalyzed)]
    public string GroupId { get; set; }

    [ElasticProperty(Store = true, Index = FieldIndexOption.Analyzed)]
    public string FilePath { get; set; }
}

if we index some documents as follows

void Main()
{
    var settings = new ConnectionSettings(new Uri("http://localhost:9200"));            
    var client = new ElasticClient(settings);

    client.Index<ImportFile>(
        new ImportFile{
            FileName = "Group-1.uhh",
            FilePath = "",
            GroupId = "0ae1206d0644eabd82ae490e612732df" + 
                      "5da2cd141fdee70dc64207f86c96094"
        },
        index => index
            .Index("reviewer-bdd-test-index")
            .Type("importFile")
            .Refresh());

    client.Index<ImportFile>(
        new ImportFile
        {
            FileName = "group-1.uhh",
            FilePath = "",
            GroupId = "0ae1206d0644eabd82ae490e612732df" + 
                      "5da2cd141fdee70dc64207f86c96094"
        },
        index => index
            .Index("reviewer-bdd-test-index")
            .Type("importFile")
            .Refresh());

    var results = client.Search<ImportFile>(s => s
                .Index("reviewer-bdd-test-index")
                .Type("importFile")
                .Query(q => q
                   .Filtered(fq => fq
                        .Filter(f => f
                            .Term(p => p.FileName, "Group-1.uhh")
                        )
                    )
                )
            );

    Console.WriteLine(string.Format("{0} {1}", results.RequestInformation.RequestMethod, results.RequestInformation.RequestUrl));
    Console.WriteLine(Encoding.UTF8.GetString(results.RequestInformation.Request)); 
    Console.WriteLine("Matching document count: {0}", results.Documents.Count());
}

the following is output in the console

POST http://localhost:9200/reviewer-bdd-test-index/importFile/_search
{
  "query": {
    "filtered": {
      "filter": {
        "term": {
          "fileName": "Group-1.uhh"
        }
      }
    }
  }
}
Matching document count: 0

We get no matching documents. Checking the mapping in Elasticsearch with

curl -XGET "http://localhost:9200/reviewer-bdd-test-index/_mapping"

We see that the mapping for the type importFile is

{
   "reviewer-bdd-test-index": {
      "mappings": {
         "importFile": {
            "properties": {
               "fileName": {
                  "type": "string"
               },
               "groupId": {
                  "type": "string"
               }
            }
         }
      }
   }
}

which is not what we expect; both fileName and groupId should also have "index": "not_analyzed" and filePath is not even in the mapping. Both of these are because Elasticsearch has inferred the mapping based on the documents it has been passed - fileName and groupId have been mapped as string types and will have undergone analysis with the standard analyzer, and I believe filePath has not been mapped because both seen documents had an empty string value for the field, so the standard analyzer applied to the field would not produce any tokens for the inverted index, hence the field is not included in the mapping.

So, to ensure that things work as expected, we need to add a mapping to the index before indexing any documents

void Main()
{
    var settings = new ConnectionSettings(new Uri("http://localhost:9200"));
    var client = new ElasticClient(settings);

    // Add the mapping for ImportFile to the index
    client.CreateIndex(indexSelector => indexSelector
        .Index("reviewer-bdd-test-index")
        .AddMapping<ImportFile>(mapping => mapping
            .MapFromAttributes()
        )
    );

    // ... Same as above after this point
}

Which results in

POST http://localhost:9200/reviewer-bdd-test-index/importFile/_search
{
  "query": {
    "filtered": {
      "filter": {
        "term": {
          "fileName": "Group-1.uhh"
        }
      }
    }
  }
}
Matching document count: 1

Success! We have a matching document. Checking the mapping in Elasticsearch yields what we expect

{
   "reviewer-bdd-test-index": {
      "mappings": {
         "importFile": {
            "properties": {
               "fileName": {
                  "type": "string",
                  "index": "not_analyzed"
               },
               "filePath": {
                  "type": "string",
                  "store": true
               },
               "groupId": {
                  "type": "string",
                  "index": "not_analyzed"
               }
            }
         }
      }
   }
}

Additionally, the attribute mapping could be replaced with the fluent mapping instead

var indexResult = client.CreateIndex(indexDescriptor => indexDescriptor
    .Index("reviewer-bdd-test-index")
    .AddMapping<ImportFile>(mapping => mapping
        .Type("importFile")
        .MapFromAttributes()
        .Properties(properties => properties
            .String(s => s
                .Name(file => file.FileName)
                .Store(false)
                .Index(FieldIndexOption.NotAnalyzed))
            .String(s => s
                .Name(file => file.GroupId)
                .Store(false)
                .Index(FieldIndexOption.NotAnalyzed))
            .String(s => s
                .Name(file => file.FilePath)
                .Store(true))
        )
    )
);

Either attribute mapping or fluent mapping will do at this point however, there are some things that can only be achieved with fluent mappings such as multi_fields.



来源:https://stackoverflow.com/questions/32204858/elasticsearch-nest-term-query-returns-no-results

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!