简体   繁体   中英

Searching using NEST does not return results, when querying on certain fields

I'm developing an .NET application using Elastic Search. I used ES River to index the data. Results (in Sense) look kinda like this:

 {
    "_index": "musicstore",
    "_type": "songs",
    "_id": "J2k-NjXjRa-mgWKAq0RMlw",
    "_score": 1,
    "_source": {
       "songID": 42,
       "tempo": "andante",
       "metrum": "3/4 E8",
       "intonation": "F",
       "title": "Song",
       "archiveSongNumber": "3684",
       "Year": 2000,
       "Place": "London"
    }
 },

To access the indexed data I use NEST queries similar to this:

var result = ElasticClient.Search<Song>(s => s.Query(q => q.Term(p => p.title, "Song")));

I'm having a problem that the query doesn't return any results, when I search for a certain field. For instance when I search for a title, songID, tempo or archiveSongNumber the query works fine and it returns the same results as Sense, but when I search for Year, Place, metrum, etc. the query doesn't return any results, but it should (Sense does and it should). Queries like these work (and return the right results):

var result = ElasticClient.Search<Song>(s => s.Query(q => q.Term(p => p.title, "Song")));        
var result = ElasticClient.Search<Song>(s => s.Query(q => q.Term(p => p.songID, 42)));
var result = ElasticClient.Search<Song>(s => s.Query(q => q.Term(p => p.archiveSongNumber , "3684")));

Queries like these don't return any results (but they should):

var result = ElasticClient.Search<Song>(s => s.Query(q => q.Term(p => p.Place, "London")));
var result = ElasticClient.Search<Song>(s => s.Query(q => q.Term(p => p.Year, 2000)));

What am I doing wrong? Did I mess up when I was indexing data?

Update: Mapping looks like this:

{
   "musicstore": {
      "mappings": {
         "songs": {
            "properties": {
               "Year": {
                  "type": "long"
               },
               "Place": {
                  "type": "string"
               },
               "archiveSongNumber": {
                  "type": "string"
               },
               "songID": {
                  "type": "long"
               },
               "intonation": {
                  "type": "string"
               },
               "metrum": {
                  "type": "string"
               },
               "title": {
                  "type": "string"
               },
               "tempo": {
                  "type": "string"
               }
            }
         }
      }
   }
}

Update 2:

ES river request looks like this:

PUT /_river/songs_river/_meta
{
    "type":"jdbc",
    "jdbc": {
        "driver":"com.microsoft.sqlserver.jdbc.SQLServerDriver",
        "url":"jdbc:sqlserver://ip_address:1433;databaseName=database",
        "user":"user",
        "password":"password",
        "strategy":"simple",
        "poll":"300s",
        "autocommit":true,
        "fetchsize":10,
        "max_retries":3,
        "max_retries_wait":"10s",
        "index":"musicstore", 
        "type":"songs",
        "analysis": {
            "analyzer" :{ 
                "whitespace" :{ 
                    "type" : "whitespace",
                    "filter":"lowercase"
                }
            }
        },
        "sql":"some_sql_query"
    }
}

ES client configuration looks like this:

private static ElasticClient ElasticClient
{
    get
    {
        Uri localhost = new Uri("http://localhost:9200");
        var setting = new ConnectionSettings(localhost);
        setting.SetDefaultIndex("musicstore").MapDefaultTypeNames(d => d.Add(typeof(Song), "songs"));
        setting.SetConnectionStatusHandler(c =>
        {
            if (!c.Success)
                throw new Exception(c.ToString());
        });
        return new ElasticClient(setting);
    }
}

From looking at your mapping, the issue here is most likely that all of your fields are being analyzed when indexing, but you are using term queries with NEST, which are not analyzed , meaning they will only find exact matches. If you don't explicitly specify an analyzer in your mappings, Elasticsearch defaults to the standard analyzer .

When you perform a search in Elasticsearch using a query string, like you're doing in Sense: GET _search/?q=Place:London , a query string query is what's being run by Elasticsearch, which is different than a term query .

From your examples though, it doesn't look like you are actually using query string syntax . You probably want a match query instead:

client.Search<Song>(s => s
    .Query(q => q
        .Match(m => m
            .OnField(p => p.Place)
            .Query("London")
        )
    )
);

If you do however want a query string query like the one you're performing with Sense, than you can use QueryString :

client.Search<Song>(s => s
    .Query(q => q
        .QueryString(qs => qs
            .OnFields(p => p.Place)
            .Query("London")
        )
    )
);

Hope that helps. I suggest checking out the getting started guide , specifically the section on exact values vs. full text .

Add "keyword" suffix to your Term Field :

var result = ElasticClient.Search<Song>(s => s
            .Query(q => q
            .Term(p => p
                        .Field(x => x.Year.Suffix("keyword")).Value(2000))));

Try it, it will work!

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