问题描述:

This is for elasticsearch 2.3

Let's pretend I have a mapping of the sort:

index1:

'title': {'type': 'string'},

'tags': {'type': 'string', 'index': 'not_analyzed'}

index2:

'title': {'type': 'string'},

'tags': {'type': 'string', 'index': 'not_analyzed'},

'tag_special': {'type': 'string', 'index': 'not_analyzed'}

Note: when pushing to index1 and index2, the "tags" is an array of strings. In index2 the "tag_special" is just a single string

What I would like to accomplish is a query where we query across both indexes, looking first and foremost for exact term matches in the array of tags in index1 or the single string value of tag_special in index2, and boost those matches to the top of the heap. I would then like to take the same query and then run a normal match query against the title field across both indexes

example documents

{

"_index": "index1",

"_type": "index1",

"title": "Test Doc 1",

"tags": ["tag-1", "tag-2"]

}

{

"_index": "index1",

"_type": "index1",

"title": "Test Doc 2",

"tags": ["tag-1"]

}

{

"_index": "index1",

"_type": "index1",

"title": "Test Doc 3",

"tags": ["tag-2", "tag-3"]

}

{

"_index": "index2",

"_type": "index2",

"title": "Test Doc inx2 1",

"tags": ["tag-1", "tag-2"],

"tag_special": "tag-1"

}

{

"_index": "index2",

"_type": "index2",

"title": "Test Doc inx2 2",

"tags": ["tag-2"]

}

{

"_index": "index2",

"_type": "index2",

"title": "Test Doc inx2 3",

"tags": ["tag-3"],

"tag_special": "tag-4"

}

Absolutely nothing I'm trying is quite working out.

"query": {

"bool": {

"should": [

{"term": {"tags": "tag-2"}},

]

}

}

returns nothing, curiously, but

"query": {

"bool": {

"should": [

{"match": {"tags": "tag-2"}},

]

}

}

returns too much (it'll return all posts if you look for "tag-2" as its using an analyzer and search for "tag" as well as "2")

Once I can term query against an array of strings, I need to boost the exact matches to the top of the results, and then utilize a standard match against the title field

It should be OK that none of the term queries actually match anything, they need to be totally optional. Therefore the term matches cannot act as filters or constant_score, as it I need it to be possible to make a normal title query and have the results ordered by the score value

What I have so far is

"query": {

"bool": {

"should": [

{"term": {"tags": "tag-2"}},

{"term": {"tag_special": "tag-2"}},

{"match": {"title": {"query": "tag-2", "operator": "and"}}}

],

}

}

but as of right this second, nothing gets returned. Using multi_match also seems to be out because it uses the match clause

I feel what I'm trying to accomplish is actually pretty simple, like there's just one thing that im missing here, and im here because after hours of trial and error it's near quitting time and I'm hoping I got something to go on tomorrow morning haha

Thanks for your time!

网友答案:

I did same as you did and I got results for your example document. There was a small issue in the query you have posted as there is "," in the bool query although there is only one should. So the query should be like this.

"query": {
        "bool": {
            "should": [
                {"term": {"tags": "tag-2"}},
                {"term": {"tag_special": "tag-2"}},
                {"match": {"title": {"query": "tag-2", "operator": "and"}}}
            ]
        }
    }

if this didn't work make sure you have set tags and tag_special fields as not_analyzed

GET index1/_mapping should show this result

"index1": {
  "mappings": {
     "index1": {
        "properties": {
           "tags": {
              "type": "string",
              "index": "not_analyzed"
           },
           "title": {
              "type": "string"
           }
        }
     }
  }
}

if the tags and tag_special fieds are analyzed the term query will not give out any results

网友答案:

Figured out my issue. It has nothing to do with anything, but I'll answer it anyways.

I had two issues actually that would not have displayed here, but serves as a cautionary tale.

  1. I forgot to actually SEND the mapping. So each time I was "re-creating" the index, the map would just create its own self based on assumptions of what documents I was pumping into it.
  2. Once I actually sent the mapping, it still didn't work, oddly after sending the mapping and waiting for the documents to be collected from the original database, I couldn't see any mapping information until the documents were uploaded to ES. I discovered that I had accidentally use array as a type for one of my unrelated fields in the mapping, instead of string. And apparently instead of telling me there was an error, it just decided to invalidate the map entirely and not bother until the documents were uploaded. The moment I changed array to string in that one field, everything worked like a charm.
相关阅读:
Top