用相关项目填充Elasticsearch时出错



在我的laravel 5.7应用程序中,我使用Elasticsearch,并且我有批量功能来用相关的vote_items填充我的投票。

问题是我无法添加相关vote_items的数组,因为我收到错误:

{"error":{"root_cause":[{"type":"mapper_parsing_exception","reason":"object mapping for [vote_items] tried to parse field [null] as object, but found a concrete value"}],"type":"mapper_parsing_exception","reason":"object mapping for [vote_items] tried to parse field [null] as object, but found a concrete value"},"status":400}

at方法(错误行被取消注释并标记(:

public static function bulkVotesToElastic()
{
$elastic = app(AppElasticElastic::class);
$elasticsearch_root_index  = config('app.elasticsearch_root_index');
$elasticsearch_type        = with(new Vote)->getElasticsearchType();
Vote::chunk(100, function ($Votes) use ($elastic, $elasticsearch_root_index, $elasticsearch_type) {
foreach ($Votes as $nextVote) {
if ($nextVote->status!= 'A') continue;   // only active votes must be saved in elasticsearch
$voteCategory= $nextVote->voteCategory;
if (empty($voteCategory)) continue;     // only votes with valid category must be saved in elasticsearch
if ( !$voteCategory->active ) continue; // only votes with active category must be saved in elasticsearch
$voteItems = VoteItem
::getByVote($nextVote->id)
->orderBy('ordering', 'asc')
->get();
$relatedVoteItemsList= [];
foreach ($voteItems as $nextVoteItem) {
$relatedVoteItemsList[]= $nextVoteItem->name;     // THIS LINE RAISE ERROR!
//                    $relatedVoteItemsList[]= [ $nextVoteItem->name ]; // THIS LINE RAISE ERROR TOO!
//                    $relatedVoteItemsList[]= [ 'vote_item_name' => $nextVoteItem->name ];   // THIS LINE DOES NOT RAISE ERROR!
}
$elastic->index([
'index' => $elasticsearch_root_index,
'type'  => $elasticsearch_type,
'id'    => $nextVote->id,
'body'  => [
'id'          => $nextVote->id,
'slug'        => $nextVote->slug,
'name'        => $nextVote->name,
'description' => $nextVote->description,
'created_at'  => $nextVote->created_at,
'vote_items'  => $relatedVoteItemsList,
'category_id' => $voteCategory->id,
'category'    => [
'name'         => $voteCategory->name,
'slug'         => $voteCategory->slug,
'created_at'   => $voteCategory->created_at,
],
]
]);
}
});
}

如果我取消注释行:

//                    $relatedVoteItemsList[]= [ 'vote_item_name' => $nextVoteItem->name ];   // THIS LINE DOES NOT RAISE ERROR!

和上面的注释2行,然后批量工作可以,但我的搜索条件不适用于vote_items

$elasticQuery = [
"bool" => [
'must' => [
[
"multi_match" => [
"query"  => $text,
"type"   => "cross_fields",
"fields" => [
"name^4",
"description",
"vote_items^2"
]
],
],
],
]
];

我不知道哪种语法是有效的?

更新#2:查看提供的文档链接,我看到:

PUT my_index
{
"mappings": {
"_doc": {
"properties": {
"user": {
"type": "nested" 
}
}
}
}
}

我想在保存我的数据时,我必须指出一些数据是嵌套的。

我将批量功能重新制作为:

foreach ($Votes as $nextVote) {
if ($nextVote->status!= 'A') continue;   // only active votes must be saved in elasticsearch
$voteCategory= $nextVote->voteCategory;
if (empty($voteCategory)) continue;     // only votes with valid category must be saved in elasticsearch
if ( !$voteCategory->active ) continue; // only votes with active category must be saved in elasticsearch
$voteItems = VoteItem
::getByVote($nextVote->id)
->orderBy('ordering', 'asc')
->get();
$relatedVoteItemsList= [];
foreach ($voteItems as $nextVoteItem) {
$relatedVoteItemsList[]= [ 'vote_item_name' => $nextVoteItem->name ]; // VALID STRUCTURE ?
}
$elastic->index([
'index' => $elasticsearch_root_index,
'type'  => $elasticsearch_type,
'id'    => $nextVote->id,
'body'  => [
'id'          => $nextVote->id,
'slug'        => $nextVote->slug,
'name'        => $nextVote->name,
'description' => $nextVote->description,
'created_at'  => $nextVote->created_at,
'vote_items'  => $relatedVoteItemsList,
'category_id' => $voteCategory->id,
'category'    => [
'name'         => $voteCategory->name,
'slug'         => $voteCategory->slug,
'created_at'   => $voteCategory->created_at,
],
]
]);

但看看地图:

http://localhost:9200/_mapping :
"select_vote": {
"mappings": {
"vote": {
"properties": {
"category": {
"properties": {
"created_at": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"slug": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
},
"category_id": {
"type": "long"
},
"created_at": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"creator_id": {
"type": "long"
},
"description": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"id": {
"type": "long"
},
"image": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"is_homepage": {
"type": "long"
},
"is_quiz": {
"type": "long"
},
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"ordering": {
"type": "long"
},
"slug": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"status": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"vote_category_id": {
"type": "long"
},
"vote_items": {
"properties": {
"is_correct": {
"type": "long"
},
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"vote_item_id": {
"type": "long"
},
"vote_item_name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"vote_items": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
}
}
}
}

我没有看到vote_items标记为嵌套,但看看我支持的示例,它必须是?。写入vote_items将被标记为嵌套的数据的正确方法是什么?

谢谢!

似乎vote_items是嵌套类型字段。类似这样的东西:

{
"vote_items" : {
"type": "nested",
"properties": {
"vote_item_name": {
"type": "keyword"
}
}
}
}

这就是以下工作的原因:

$relatedVoteItemsList[]= [ 'vote_item_name' => $nextVoteItem->name ];

要查询嵌套字段,需要使用以下语法:

{
"query": {
"nested": {
"path": "vote_items",
"query": {
"bool": {
"must": [
{
"match": {
"vote_items.vote_item_name": "xyz"
}
}
]
}
}
}
}
}

请注意,nested块具有path(更不用说要查询的嵌套类型字段(和query(要在嵌套对象上运行的查询(。还要注意,字段名称应该是完全限定的名称,即<nested_field_name>.<property>,在本例中为vote_items.vote_item_name

注意:上面的查询是如何使用索引映射的字段查询嵌套字段的示例。请根据您的需要进行修改

有关如何查询嵌套字段的详细信息,请参阅此处。

你看到这个了吗https://github.com/elasticquent/Elasticquent插件?它有索引和映射示例,如:

protected $mappingProperties = array(
'title' => array(
'type' => 'string',
'analyzer' => 'standard'
)
);

如果你想根据你的映射属性设置模型的类型映射,你可以使用:

Book::putMapping($ignoreConflicts=true(;

最新更新