Ошибка заполнения Elasticsearch связанными элементами - PullRequest
0 голосов
/ 24 ноября 2018

В моем приложении laravel 5.7 я использую Elasticsearch, и у меня есть функция массового заполнения, чтобы заполнить мои голоса соответствующими элементами voice_items.

Проблема в том, что я не могу добавить массив связанных элементов poll_sems, поскольку получаю ошибку:

{"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(\App\Elastic\Elastic::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 строки выше, тогда массовые работыхорошо, но мое условие поиска не работает для voice_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
}
}
}
}
}
}
}
}
}

Я не вижу, что voice_items помечен как вложенный, но, глядя на пример, полагаю, он должен?Как правильно записать мои данные, чтобы в качестве элемента_оценки voice_items была помечена как вложенная?

Спасибо!

Ответы [ 2 ]

0 голосов
/ 28 ноября 2018

Вы видели этот https://github.com/elasticquent/Elasticquent плагин?Он имеет примеры индексов и сопоставления, например:

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

Если вы хотите настроить сопоставление типов модели на основе ваших свойств сопоставления, вы можете использовать:

Book :: putMapping ($ignoreConflicts = true);

0 голосов
/ 24 ноября 2018

Кажется, 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.

ПРИМЕЧАНИЕ. Приведенный выше запрос является примером того, как запросить вложенное поле, используя поля вашего индексаотображение.Пожалуйста, измените в соответствии с вашими потребностями.

Подробнее о том, как запросить вложенные поля , см. здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...