Problem/Motivation

I am unable to render fields using the SearchApiEntityField plugin in views, even when the search query returns a result. I am using search_api_opensearch as the back end.

Tracking this down I think this is because, in SearchAPIEntityField there are the following lines in getItems:

if ($values->search_api_datasource != $this->getDatasourceId()) {
  return [];
}

Inspecting $values I see that $values->search_api_datasource is an array of one data source id whereas $this->getDatasourceId() is a string. The data source ids to match. I don't know whether search_api_datasource should not be an array, or whether the if statement is incorrect.

Remaining tasks

Issue fork search_api-3262507

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

rlmumford created an issue. See original summary.

rlmumford’s picture

Digging further, it looks like search_api_datasource is not expected to be set on the ResultRow directly at all but rather would be lazy loaded when required by \Drupal\search_api\Plugin\views\ResultRow. A solution might therefore be to not copy these fields on to the ResultRow if they are returned by the Backend.

rlmumford’s picture

Status: Active » Needs review

Added a MR that resolves my problem, I'm not sure whether this should be something that should be fixed in the backend providers or here though. Another alternative would be to replace the checks on `$values->search_api_datasource` with explicit checks on `$values->_item->getDatasourceId()`

rlmumford’s picture

StatusFileSize
new1.07 KB

Adding a patch file as the test bot doesn't seem to like merge requests.

acbramley’s picture

Having the same issue, it also throws an exception when using a rendered entity because isValidDatasource is called with an array rather than a string which throws an exception.

EDIT: Should mention patch #5 fixed it for me :)

kalpaitch’s picture

I'm having the same issue, and patch #5 does solve the issue for me too.

I wonder if we could avoid the duplication of configured fields a bit by adding a getLazyLoadFields() method or some such to ResultRow instead of re-creating the array in SearchApiQuery?

I mention because the solution used in patch #5 is used once already in SearchApiQuery::addField(), so we're duplicating this twice in the same file...

  public function addField($table, $field, $alias = '', array $params = []) {
    // Ignore calls for built-in fields which don't need to be retrieved.
    $built_in = [
      'search_api_id' => TRUE,
      'search_api_datasource' => TRUE,
      'search_api_language' => TRUE,
      'search_api_relevance' => TRUE,
      'search_api_excerpt' => TRUE,
    ];
    if (isset($built_in[$field])) {
      return $field;
    }
...
kalpaitch’s picture

StatusFileSize
new1.88 KB
new2.02 KB

I think this is the best approach which brings the two existing methods together with minimal impact on additional classes and methods.

There are only 2 calls to getFields() methods in the SearchApiQuery class so I think this covers all use cases for now.

kalpaitch’s picture

StatusFileSize
new1.88 KB
new2.02 KB
acbramley’s picture

Does that mean these fields shouldn't be indexed in the first place? If so we can simply stop search_api_opensearch indexing them here

kalpaitch’s picture

@acbramley That might also be the case. Either way this patch still seems necessary, they're not fields that views should be querying.

It might be worth referring comment #11 back to #3267797: Indexed Fields in views empty, to see if any work is actually needed there.

pebosi’s picture

#10 works for me

kalpaitch’s picture

@pebosi could you mark as reviewed pls? (assuming you have)

varshith’s picture

Status: Needs review » Reviewed & tested by the community

The patch at #10 works fine.
The code is pretty straightforward and I am marking it as reviewed.

acbramley’s picture

StatusFileSize
new2.38 KB

Rerolled

acbramley’s picture

StatusFileSize
new1.89 KB

Reroll, the list() change was already committed.

longwave’s picture

I found this issue via #3313519: TypeError: Illegal offset type in isset or empty in Drupal\search_api\Entity\Index->isValidDatasource() when using rendered item field

What is the purpose of putting search_api_id, search_api_datasource and search_api_language into the index in the first place? An alternative fix is to skip indexing these items at all in the OpenSearch case, and that seems to work with no side effects for my use case.

drunken monkey’s picture

Status: Reviewed & tested by the community » Needs review
StatusFileSize
new3.32 KB
new2.87 KB

Thanks a lot for posting this, and sorry it took me such a long time to reply.

The patch looks pretty good and the problem seems real, based on the feedback. (I’m not using the Search API OpenSearch module myself.)
Also, indexing those fields migth be necessary, as \Drupal\search_api\Query\QueryInterface::sort() specifies that it should be possible to sort by them. (Filtering by language or datasource is also allowed.) In my opinion, the returned result items should still not include those fields (as they are not configured fields on the index), so a fix to the Search API OpenSearch module might be in order, too, but it definitely cannot hurt to guard against this problem here, too.

However, if $this->ignoredFieldValues is never written to anyways, couldn’t it just be a constant?
Furthermore, why not just make \Drupal\search_api\Plugin\views\ResultRow::$lazyLoad public (or a constant) and use that directly?
Patch attached, please review. (Would probably need a change record, too, though, in this form, due to the deprecation of \Drupal\search_api\Plugin\views\ResultRow::$lazyLoad. (Only relevant for any sub-classes of \Drupal\search_api\Plugin\views\ResultRow, but still.)

bobooon’s picture

+1 RTBC #19

Using search_api and search_api_opensearch with this patch resolved the fatal errors that were happening on search.

drunken monkey’s picture

Status: Needs review » Fixed

Thanks for testing and reporting back, good to hear this worked! (And even fixed a fatal error, in your case!)
Committed the patch and posted a change record.
Thanks again, everyone!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.