Егор Лебедев
Егор Лебедев

Reputation: 1336

Can't get join query in elastic

I got elasticsearch version 7.3 and two indexes, profiles and purchases, here is their mappings:

\purchases
{
    "purchases": {
        "mappings": {
            "properties": {
                "product": {
                    "type": "keyword"
                },
                "profile": {
                    "type": "join",
                    "eager_global_ordinals": true,
                    "relations": {
                        "profiles": "purchases"
                    }
                }
            }
        }
    }
}

\profiles
{
    "profiles": {
        "mappings": {
            "properties": {
                "user": {
                    "type": "keyword"
                }
            }
        }
    }
}

I added one profile with user:abc, _id:1 and two purchases this way

{
    "profile": {"name": "profiles", "parent": "1"},
    "product" : "tomato",
}
{
    "profile": {"name": "profiles", "parent": "1"},
    "product" : "tomato 2",
}

Then I do search query for purchases

{
    "query": {
    "has_parent": {
      "parent_type": "profiles",
      "query": {
        "query_string": {
          "query": "user:abc"
        }
      }
    }
  }
}

And I get empty result, what is wrong?

Upvotes: 1

Views: 87

Answers (1)

apt-get_install_skill
apt-get_install_skill

Reputation: 2908

As stated in the documentation of the Join datatype you can not create parent-child-relationships over multiple indices:

The join datatype is a special field that creates parent/child relation within documents of the same index.

If you would like to use the join datatype, you have to model it in one index.

UPDATE

This is how your mapping and the Indexing of the documents would look like:

PUT profiles-purchases-index
{
  "mappings": {
    "properties": {
      "user":{
        "type": "keyword"
      },
      "product":{
        "type": "keyword"
      },
      "profile":{
        "type": "join",
        "relations":{
          "profiles": "purchases"
        }
      }
    }
  }
}

Index parent document:

PUT profiles-purchases-index/_doc/1
{
  "user": "abc",
  "profile": "profiles"
}

Index child documents:

PUT profiles-purchases-index/_doc/2?routing=1
{
  "product": "tomato",
  "profile":{
    "name": "purchases",
    "parent": 1
  }
}

PUT profiles-purchases-index/_doc/3?routing=1
{
  "product": "tomato 2",
  "profile":{
    "name": "purchases",
    "parent": 1
  }
}

Run Query:

GET profiles-purchases-index/_search
{
  "query": {
    "has_parent": {
      "parent_type": "profiles",
      "query": {
        "match": {
          "user": "abc"
        }
      }
    }
  }
}

Response:

{
  ...
    "hits" : [
      {
        "_index" : "profiles-purchases-index",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 1.0,
        "_routing" : "1",
        "_source" : {
          "product" : "tomato",
          "profile" : {
            "name" : "purchases",
            "parent" : 1
          }
        }
      },
      {
        "_index" : "profiles-purchases-index",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 1.0,
        "_routing" : "1",
        "_source" : {
          "product" : "tomato 2",
          "profile" : {
            "name" : "purchases",
            "parent" : 1
          }
        }
      }
    ]
  }
}

Notice that you have to set the routing parameter to index the child documents. But please refer to the documentation for that.

Upvotes: 1

Related Questions