PHP ElasticSearch how to set mapping before indexi

2019-05-31 09:33发布

问题:

I'm using laravel and elasticsearch-php to index and store data to elastic, my problem is that elastisearch uses from dynamic mapping but I need to set my custom mapping. How can I use from my mapping?

Bellow is my code:

$client = \Elasticsearch\ClientBuilder::create()->build();

        $mappingData = array(
            'index' => 'promote_kmp',
            'body' => array(
                'mappings' => $resource->getMappingProperties()
            )
        );
        $client->indices()->create($mappingData);

        $params = [
            'type' => 'resources',
            'id' => uniqid(),
            'body' => [
                'id' => $resource->id,
                'name' => $resource->name,
                'display_name_en' => $resource->display_name_en,
                'display_name_pr' => $resource->display_name_pr,
                'display_name_pa' => $resource->display_name_pa,
                'table_name'      => $resource->table_name,
                'model_name'      => $resource->model_name,
                'in_sidemenu'     => $resource->in_sidemenu,
                'icon_class'      => $resource->icon_class,
                'created_at'      => $resource->created_at,
                'created_by'      => $user,
            ]
        ];

        //$response = $client->indices()->create($resource->getMappingProperties());

        $client->index($params);

$resource->getMappingProperties() get the mapping array I have set in model. but when I want to index a record it says IndexAlreadyExistsException[[promote_kmp] already exists]. This question arise when I want to search for date field searching is not properly working and I guess that mapping is not true.

回答1:

As I was saying in comments.

The code is executing the creation of index every time you want to query. But the index must be created only once.

So it should work like the migration for the DB's.

The only idea I can give you is to make a command to generate the index. So that you could just

$ artisan elasticsearch:generate <index>

About the code, what I've done for our case, made the index with a way to inject the types, plus a way to create them into elasticsearch:

interface Index {

  /**
   * @param Type[] $types Index types (resources)
   */
  function setTypes(array $types);

  /**
   * Generate the index and the types into the elasticsearch
   */
  function create();

}

Then the types should generate the mappings and the type name (as /<index>/<type>, like:

interface Type {

  /**
   * @return string The type name
   */
   function getName();

  /**
   * @return array The type mapping 
   */
  function getMapping();

}

So (somewhere), you would create the class (this could be better):

$myIndex = new MyIndex();
$myIndex->setTypes([
  new MyFirstType(),
  new MySecondType(),
  //...
]);
$myIndex->create();

I hope this helps.