繁体   English   中英

如何添加嵌套 object 而不是用 PHP 替换 ElasticSearch 中的现有一个

[英]How to add nested object instead of replacing an existing one in ElasticSearch with PHP

我有一个具有“地址”属性的用户“列表”。 一个用户可以有多个地址。 我使用嵌套类型作为地址。 在我的地址中,我有一个“房间”属性,我也使用了嵌套类型。 在我的前端,我有一个表单允许用户添加新房间。 这样做时,可以将房间添加到现有地址或创建新地址。

当我创建一个新地址时,现有地址将被新地址替换。 我需要添加新地址,以便我有一个地址数组。 如果我使用现有地址,我需要将新房间添加到该地址。

我的索引

$params = [
    'index' => 'users',
    'body' => [
        'settings' => [
            'number_of_shards' => 3,
            'number_of_replicas' => 2
        ],
        'mappings' => [
            'properties' => [
                'firstname' => [
                    'type' => 'text'
                ],
                'surname' => [
                    'type' => 'text'
                ],
                'email' => [
                    'type' => 'text'
                ],
                "addresses" => [
                    'type' => 'nested',
                   'properties' => [
                       "id" => [
                           'type' => 'integer'
                       ],
                       "address" => [
                           'type' => 'text'
                       ],
                       "zipcode" => [
                           'type' => 'text'
                       ],
                       "city" => [
                           'type' => 'text'
                       ],
                       "country" => [
                           'type' => 'text'
                       ],
                       "rooms" => [
                           'type' => 'nested',
                           'properties' => [
                               "id" => [
                                   'type' => 'integer'
                               ],
                               "name" => [
                                   'type' => 'text'
                               ],
                           ]
                       ]
                   ]
               ]
            ]
        ]
    ]
];
$response = $client->indices()->create($params);

更新 function

$params = [
    'index' => 'users',
    'id'    => $user_id,
    'body' => [
        'doc' => [
            'addresses' => [
                "id" => $address->id,
                "address" => $address->address,
                "zipcode" => $address->zipcode,
                "city" => $address->locality,
                "country" => $address->country,
                "rooms" => [
                    "id" => $room->id,
                    "name" => $room->room_name,
                ]
            ]
        ]
    ]
];
$client->update($params);

如何添加新地址?

您可以在无痛脚本中使用add方法:

$params = [
 'index' => 'users',
  'id'    => $user_id,
  'body' => [
        'script' => [
        'lang' => "painless",
        'inline' => "ctx._source.addresses.add(params.data)",
        'params' => [
            'data' => [
                "id" => $address->id,
                "address" => $address->address,
                "zipcode" => $address->zipcode,
                "city" => $address->locality,
                "country" => $address->country,
                "rooms" => [
                    "id" => $room->id,
                    "name" => $room->room_name,
            ]
        ]
    ]
  ]
];

$result = $client->update($params);

作为旁注:

Object 字段类型让我们进行如下搜索:

“任何地址上的财产 A 和/或 B”

嵌套字段类型搜索,例如:

“位于同一地址的物业 A 和/或 B”

并非所有嵌套字段都必须是嵌套类型。 仅当您需要保持相同子项的属性之间的关系才能进行查询时。

我使用llermaly建议的无痛脚本找到了解决方案。 我不得不调整一些东西,并添加了一个条件,以便能够将房间添加到现有地址。

注意:在我用来添加新房间的表格中,用户可以在 select 上创建一个现有地址。 我必须检查地址是否是新地址并调整我的代码......

if($request->existing_id === 0) {  // if 0 -> the address is a new one
  $params = [
   'index' => 'users',
    'id'    => $user_id,
    'body' => [
        'script' => [
        'lang' => "painless",
        'inline' => "if (!(ctx._source.addresses instanceof Collection)) {ctx._source.addresses = new ArrayList(); ctx._source.addresses.add(params.data)} else {ctx._source.addresses.add(params.data)}",
        'params' => [
            'data' => [
                "id" => $address->id,
                "address" => $address->address,
                "zipcode" => $address->zipcode,
                "city" => $address->locality,
                "country" => $address->country,
                "rooms" => [
                    "id" => $room->id,
                    "name" => $room->room_name,
            ]
        ]
      ]
    ]
  ];
} else {
  // first I need to know the index of the selected address
  $params = [
    'index' => 'users',
    'id'    => $request->user
  ];
  $response = $client->get($params);
  $addresses = $response["_source"]["addresses"];
  $targetAddress = array_search($address->id, array_column($addresses, 'id'));
 
  // Then, I can add a room to it
  $params = [
    'index' => 'users',
    'id'    => $request->user,
    'body' => [
      'script' => [
        'lang' => "painless",
        "source" => "if (!(ctx._source.addresses[".$targetAddress."].rooms instanceof Collection)) {ctx._source.addresses[".$targetAddress."].rooms = new ArrayList(); ctx._source.addresses[".$targetAddress."].rooms.add(params.data)} else {ctx._source.addresses[".$targetAddress."].rooms.add(params.data)}",
        'params' => [
          'data' => [
            "id" => $room->id,
            "name" => $room->room_name,

          ]
        ]
      ]
    ]
  ];
  $client->update($params);
}

$result = $client->update($params);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM