![](/img/trans.png)
[英]How to add strings to an existing object without replacing it in a loop?
[英]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.