Closed (fixed)
Project:
Search API Solr
Version:
4.x-dev
Component:
Code
Priority:
Normal
Category:
Bug report
Assigned:
Unassigned
Reporter:
Created:
19 Jun 2020 at 21:05 UTC
Updated:
5 Mar 2021 at 20:49 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #2
karlsheaComment #3
mkalkbrennerThe hook should be invoked within function getPropertyPathCardinality()
Two more things should be dicussed in general.
Isn't it better to introduce events instead of new hooks.
Can you provide a concrete example when this "hook" is needed? I ask myself if getPropertyPathCardinality() itself could be improved.
Comment #4
karlsheaHey thanks for taking a look! #3059170-6: Referencing of User Entities via "Group Membership" using referencing entity is an example of where I'm hitting this issue (and the linked sandbox project shows how I'm handling it with the hook), and the patch at #3050475-21: SearchApiSolrBackend is setting incorrect prefix to Search API reverse entity references is hard-coding a fix for reverse entity references (since this is broken again in 4.x).
In summary, let's say a custom processor is adding an entity type property (exactly like ReverseEntityReferences). Even if
is_listis set on that property,getPropertyPathCardinality()is only looking at the target field storage definition to determine cardinality. So then this happens:getPropertyPathCardinality()returns "1" in this situation for the final field, even though when indexing actually happens there are multiple entities added by the processor, so Solr errors out giving an error about needing a multi-valued field.> The hook should be invoked within function getPropertyPathCardinality()
I initially thought that too, but
getPropertyPathCardinality()is recursive and in order to fix the problem you need to look at the full property path, not the nested path.It could probably also be an event? I was just following the existing patterns in the module.
One thing that occurred to me just now is that maybe
getPropertyPathCardinality()needs to short-circuit any time it hits anis_listproperty and immediately returnCARDINALITY_UNLIMITED? That would probably fix the issue without the hook.Comment #5
karlshea> One thing that occurred to me just now is that maybe
getPropertyPathCardinality()needs to short-circuit any time it hits an is_list property and immediately returnCARDINALITY_UNLIMITED? That would probably fix the issue without the hook.I just tried this and it didn't work. It looks like
getPropertyPathCardinality()only runs before the processors, so it never actually checks anything a processor adds and always returns "1".Maybe it needs to run again (or only after) all the processors with the "add_properties" stage have run?
Comment #6
mkalkbrennerYou can simply use the existing hook hook_search_api_solr_field_mapping_alter(). Just prefix the field name as required. For example "sm_" stands for "String Multiple":
Comment #7
karlsheaSorry, but that does not work:
Solr output:
This is an option to fix #3050475 without hard-coding "search_api_reverse_entity_reference" in `getPropertyPathCardinality()` so that other modules can do the same thing Reverse Entity References (which is currently broken) are trying to do.
Comment #8
mkalkbrenneruid?
Comment #9
karlsheaOops, copied the wrong field! It does look like it's working, it has both!
It looks like that hook is also called for a view, so I'm assuming the view is using the correct re-mapped field as well?
It sounds like your suggestion to fix #3050475: SearchApiSolrBackend is setting incorrect prefix to Search API reverse entity references is:
I spent a lot of time months ago figuring out what was going wrong with Reverse Entity References and also a module I was writing that did something similar, and it seemed like there needed to be a better way to fix the issue with child fields. I'd be happy to change how this patch works (or how a patch for #3050475 would work) but I'm out of ideas about what the right approach is from the perspective of the module maintainers.
If this is the direction you're suggesting I can change the patch, but it just seems incredibly fragile.
Comment #10
karlsheaThis is what I've got to fix Reverse Entity References—is this what you were thinking?
Comment #11
mkalkbrennerThe hook implementation seems to be right. But obviously it is an individual solution. It would be better to have a generic solution within the module that also doesn't depend on a hardcoded name.
By reviewing the code, I wonder if we just need to change the order and give "lists" precedence over the storage cardinality.
Comment #12
mkalkbrennerUploaded wrong patch :-(
Here is the right one.
Comment #13
karlsheaThis is the issue I'm seeing now:
So
isset($properies[$key])always fails.What's strange is that
$properties['gid']is never true, but "its_gid" shows up in the index. It's almost as if this is never run after the processor adds the fields.Comment #14
karlsheaMaybe a little closer:
Custom processor properties are added in search_api's
Entity\Index::getPropertyDefinitions($datasource_id).The only place
getPropertyPathCardinality()is called is inSearchApiSolrBackend($this->getPropertyPathCardinality($field->getPropertyPath(), $datasource->getPropertyDefinitions())).However, search_api's
Plugin\search_api\datasource\ContentEntity::getPropertyDefinitions()(which is what gets passed togetPropertyPathCardinality()doesn't return the property list from Entity\Index. It only returns field definitions from Entity Field Manager—none of the processor's fields will ever be there.That must be why the other issue's patch was just hard-coding the key path name, because the field definition from the processor will never exist in the array.
Comment #15
karlsheaAnd this seems to be where the logic may need to be improved.
SearchApiSolrBackend::formatSolrNames:The other issue is that even if the field were there (the definition for 'gid' is in
$fields, which is being looped over), it's checking 'gid', which is NOT a list. The'is_list' => TRUEis set in ReverseEntityReferences, which 'gid' is nested through, but that property doesn't appear to be checked anywhere.It almost seems like where I commented "Falls through" that entire try/catch where it checks by datasource property definitions needs to be replaced with
If I replace that I get
Comment #16
karlsheaAnd here's the full patch.
Comment #17
mkalkbrennerThis seems to be the missing piece. Good catch!
But your patch doesn't take into account that
$index->getPropertyDefinitions()could throw the same exception.This should be the right patch.
Comment #18
mkalkbrennerUnfortunately the tests failed:
https://github.com/mkalkbrenner/search_api_solr/runs/1405216683
The problem is that all base fields are "potential" lists:
So this "safety net" check needs to go last as it was before.
Comment #20
mkalkbrennerWether if the last patch solves the initial issue or not, it is already an important improvement. I therefore committed it.
Any further patch schould base on the current dev version.
Comment #21
karlsheaThis does fix the problem for me, so I think this can be closed. I'll also update the other issue.
Thanks so much for working through this with me, glad we figured it out!
Comment #22
mkalkbrennerThank you!
Comment #24
johnlutzUploading a patch to backport for 8.x-1.x version. This is needed by us because we are on acquia and to my knowledge they don't yet support the 4.x version.