Elasticsearch PHP add routing to child document

Viewed 263

Database Server: Elasticsearch 7.9.2 Centos 7.7

Dev env: PHP 7.3.11 MacOS

I am fairly new to Elasticsearch, so please bare with me on this one. It is driving me crazy though.

I am trying to to something very easy, but since I am from the relational database world, I need some mind bending. I have created a mapping with a parent-child relationship.

Product --> Price

This is the mapping I created:

PUT /products_pc
{
 "mappings": { 
    "properties": {
      "datafeed_id": {
        "type": "integer"
      },
      "date_add": {
        "type": "date"
      },
      "description": {
        "type": "text"
      },
      "ean": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      },
      "image_url": {
        "type": "text",
        "index": false
      },
      "name": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      },
      "sku": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      },
        "webshop_id": {
        "type": "integer"
      },
      "price": {
        "type": "float"
      },
      "url": {
        "type": "text"
      },
        "date_mod":{
          "type": "date"
        },
        "product_price" : {
          "type":"join",
          "relations": {
            "product":"price"
          }
        }
    }
  }
}

So far so good. When I manually add a product and 2 prices I can get what I would expect: 1 parent with 2 child documents.

Now on to PHP, I am able to index the parent document, but not for the child documents. Looks like I am not able to send along a routing parameter (which I can with Kibana)

This is what I tried in PHP, parent _id = 123

$hosts = ['xxx.xxx.xxx.xxx:9200'];
$client = ClientBuilder::create()
    ->setHosts($hosts)
    ->build();    

$params['body'][] = [
    'create' => [
        '_index' => 'products_pc',
        '_id' => '123_1'
    ]
];
$params['body'][] = [
    'webshop_id' => 1,
    'date_mod' => time(),
    'price' => 12,
    'url' => '',
    'product_price' => [
        'name' => 'price',
        'parent' => 123
    ]
];
$client->bulk($params);

But this does not work, as there is no routing set. If I add '_routing' => 123 below _id field I get an 400 error telling me the _routing field is wrong ("Action/metadata line [3] contains an unknown parameter [_routing]")

I have been searching for 2 days now, running in circles. All the different Elasticsearch versions are slightly different, so I have to admit that I am lost. Is there anybody who can point me my mistake? Or a hint in the right direction? It is driving me crazy. (As I am afraid it will be too simple to do...)

Thanks in advance!

1 Answers

So here we are, after 2 more days of searching... But I have found the solution it seems...

After some more hours searching I ended up at this page (again): https://elastic.co/guide/en/elasticsearch/client/php-api/current/ElasticsearchPHP_Endpoints.html#Elasticsearch_Clientbulk_bulk

And there it was, in the params list of the bulk endpoint:

$params['routing']                =  // (string) Specific routing value

Not quite sure how to use this at first, but... Then I tried this for each of the child documents, which seems to be doing the trick!

$hosts = ['xxx.xxx.xxx.xxx:9200'];
$client = ClientBuilder::create()
    ->setHosts($hosts)
    ->build();

// insert price
$params['body'][] = [
    'index' => [
        '_index' => 'products_pc',
        '_id' => '123_1',
        'routing' => 123 // <-- Insert routing here.
    ]
];
$params['body'][] = [
    'webshop_id' => 1,
    'date_mod' => time(),
    'price' => 12,
    'url' => '',
    'product_price' => [
        'name' => 'price',
        'parent' => 123 // <-- Parent _id value
    ]
];

$client->bulk($params);

As thought before, too easy actually. But I guess that is the life of a programmer.

Please be aware though, a LOT of documentation is mentioning the _routing field (Even de official docs for version 7.9: https://www.elastic.co/guide/en/elasticsearch/reference/7.9/mapping-routing-field.html As seen in the text as in the right submenu under metadata fields) but the field is actually just "routing". Might save you a couple of days ;-)

Related