简体   繁体   中英

ElasticSearch NEST - all fields are NULL

I'm trying to retrieve data from elastic search with NEST. Everything would be good, but NEST all fields return null. However, in debug mode I see that it counts the documents correctly but not showing the value of fields.

在此处输入图像描述

在此处输入图像描述

What I already did:

  • checked mapping and its seems fine to me
  • tried string query
  • tried to get source and then read data
  • tried NEST returns null instead of fields those solution did not help either
  • Renamed Product.cs field names to camelCase did not help either

Here's my code right now

public class ElasticSearch
{
    private ElasticClient _client;

    public ElasticSearch()
    {
        var node = new Uri("http://localhost:9200");
        var settings = new ConnectionSettings(node);
        settings.DefaultIndex("logsystem.logs");
        _client = new ElasticClient(settings);
    }

    public void searchResults()
    {
        var searchResults = _client.Search<Product>(s => s.AllIndices());


    }
}

Product.cs

    [BsonIgnoreExtraElements]
    public class Product
    {
        [BsonId]
        [BsonIgnore]
        public ObjectId Id { get; set; }
        [Required]
        public string Name { get; set; }
        [Required]
        public string ProductLicenseKey { get; set; }
        [Required]
        public string Action { get; set; }
        [Required]
        public string ActionName { get; set; }
        [Required]
        public string MachineId { get; set; }
    }

Mapping in ElasticSearch:

{
"logsystem.logs": {
    "mappings": {
        "properties": {
            "Action": {
                "type": "text",
                "fields": {
                    "keyword": {
                        "type": "keyword",
                        "ignore_above": 256
                    }
                }
            },
            "ActionName": {
                "type": "text",
                "fields": {
                    "keyword": {
                        "type": "keyword",
                        "ignore_above": 256
                    }
                }
            },
            "MachineId": {
                "type": "text",
                "fields": {
                    "keyword": {
                        "type": "keyword",
                        "ignore_above": 256
                    }
                }
            },
            "Name": {
                "type": "text",
                "fields": {
                    "keyword": {
                        "type": "keyword",
                        "ignore_above": 256
                    }
                }
            },
            "ProductLicenseKey": {
                "type": "text",
                "fields": {
                    "keyword": {
                        "type": "keyword",
                        "ignore_above": 256
                    }
                }
            }
        }
    }
}
}

Maybe my mapping is not right? any answer would help. Thanks.

EDIT ElasticSearch Documents get via postman:

{
"took": 11,
"timed_out": false,
"_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
},
"hits": {
    "total": {
        "value": 6,
        "relation": "eq"
    },
    "max_score": 1.0,
    "hits": [
        {
            "_index": "logsystem.logs",
            "_type": "_doc",
            "_id": "5e5c1ca2aaa6f1245cc38895",
            "_score": 1.0,
            "_source": {
                "Action": "Button",
                "ActionName": "Fixed Single Generation",
                "MachineId": "987-654-321",
                "Name": "System",
                "ProductLicenseKey": "123-456-789"
            }
        },
        {
            "_index": "logsystem.logs",
            "_type": "_doc",
            "_id": "5e5c1cb0aaa6f1245cc38896",
            "_score": 1.0,
            "_source": {
                "Action": "Button",
                "ActionName": "Fixed Multiple Generation",
                "MachineId": "987-654-321",
                "Name": "System",
                "ProductLicenseKey": "123-456-789"
            }
        },
        {
            "_index": "logsystem.logs",
            "_type": "_doc",
            "_id": "5e5c1cbdaaa6f1245cc38897",
            "_score": 1.0,
            "_source": {
                "Action": "Button",
                "ActionName": "Trackers Single Generation",
                "MachineId": "987-654-321",
                "Name": "System",
                "ProductLicenseKey": "123-456-789"
            }
        },
        {
            "_index": "logsystem.logs",
            "_type": "_doc",
            "_id": "5e5c1ccbaaa6f1245cc38898",
            "_score": 1.0,
            "_source": {
                "Action": "Button",
                "ActionName": "Trackers Multiple Generation",
                "MachineId": "987-654-321",
                "Name": "System",
                "ProductLicenseKey": "123-456-789"
            }
        },
        {
            "_index": "logsystem.logs",
            "_type": "_doc",
            "_id": "5e5c1cd3aaa6f1245cc38899",
            "_score": 1.0,
            "_source": {
                "Action": "Button",
                "ActionName": "Fixed Multiple Generation",
                "MachineId": "987-654-321",
                "Name": "System",
                "ProductLicenseKey": "123-456-789"
            }
        },
        {
            "_index": "logsystem.logs",
            "_type": "_doc",
            "_id": "5e5c1ce0aaa6f1245cc3889a",
            "_score": 1.0,
            "_source": {
                "Action": "Button",
                "ActionName": "Tree Generation",
                "MachineId": "987-654-321",
                "Name": "System",
                "ProductLicenseKey": "123-456-789"
            }
        }
    ]
 }
}

So the problem was that client tried to deserialize camelCased JSON objects keys to the POCO properties and is strict for casting.

Solution: When creating ES client add settings property DefaultFieldNameInferrer on ConnectionSettings .

    public ElasticSearch()
    {
        var node = new Uri("http://localhost:9200");
        var settings = new ConnectionSettings(node);
        settings.DefaultIndex("logsystem.logs");
        settings.DefaultFieldNameInferrer(p => p);
        _client = new ElasticClient(settings);
    }

Note: Changing this setting will cause some fields to no longer deserialize properly if they're a value type (eg int , bool , decimal , etc.) that can be null in the underlying data. If you run into that issue just add the nullable, ? , operator after the type and it should fix it.

You should use this technique for fields naming

For example

"fields": {
   "keyword": {
      "type": "keyword",
      "ignore_above": 256
    }
  }

public class Entity
{
    [Nested(Name = "fields")]
    public Fields Fields { get; set; }
}

public class Fields
{
    [Nested(Name = "keyword")]
    public Keyword Keyword { get; set; }
}

public class Keyword
{
    [Text(Name = "type")]
    public string Type { get; set; }

    [Number(Name = "ignore_above")]
    public string Ignore { get; set; }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM