Creating a backreference when the referenced field is used in two different bundle types yields "extra" fields not referenced by the originating node.
I've got the following:
Content types: Store and Lead.
Node Reference field: field_store *shared* by Lead and User.
View with base table store and a Relationship "Content: Stores(s) (field_store) - reverse (to Content)
Views Creates This:
SELECT node.title AS node_title, node.nid AS nid, field_store_node.title AS field_store_node_title, field_store_node.nid AS field_store_node_nid, 'node' AS field_data_field_store_node_entity_type
FROM
{node} node
LEFT JOIN {field_data_field_store} field_data_field_store ON node.nid = field_data_field_store.field_store_nid
LEFT JOIN {node} field_store_node ON field_data_field_store.entity_id = field_store_node.nid
WHERE (( (node.status = '1') AND (node.type IN ('store')) ))
A quick query of `field_data_field_store` with field_data_field_store.field_store_nid set to a valid store NID shows that records with a bundle values of both "store" and "user" are returned. The USER entity_id's end up getting joined as NIDs in the second Left Join. If there happens to be a NID with the corresponding UID it gets returned with the view.
I've added:
AND (field_store_node.type IN ('lead'))
via the views UI. It will get some of the bad results, but not all of them. What is needed is a way to add:
AND (field_data_field_hotel.bundle = 'lead')
This needs to be added programatically by the module where 'lead' is replaced by the bundle type of the content type on the "originating" side of the reversed relationship.
Can anybody point me to the chunk of code where this bit of magic needs to occur ?
Comment | File | Size | Author |
---|---|---|---|
#14 | backreference-nodereference.patch | 779 bytes | Dave Kopecek |
#9 | node_reference.patch | 740 bytes | Dave Kopecek |
#7 | 0001-Fix.patch | 991 bytes | Dave Kopecek |
Comments
Comment #1
Dave Kopecek>> two different bundle types yields "extra" fields not referenced by the originating node.
That was "extra rows" not "extra fields"
Comment #2
DigitalFrontiersMediaI think there's something else wrong with your query that is the cause of the fits.
Excluding the details I think are extraneous, the query generated by Views is basically doing this:
SELECT something FROM
node
LEFT JOIN node ON some_field_in_table_X_not_in_node_table = some_other_field_in_same_table_X_not_in_node_table
I'm not sure how MySQL would react to a statement requesting a join back to the same table being selected from based on two fields in some other table just happening to match each other (which in the scenario described would seem like a circular reference itself: the field_store_nid happening to reference the nid/entity_id--a 'lead' in this case--that actually contains the field_store. I don't even think the latter would be possible unless the reference field was placed on a content type and was allowed to reference the same content type the field was added to.
I'm pretty sure the Relationship "Content: Stores(s) (field_store) - reverse (to Content) is not necessary and is the cause of this problem since it is likely adding the circular node JOIN back to node. Any information that you seem to be seeking is coming from either the node table or the field_data_field_store table--both of which are already JOINed and a part of the query before your Relationship is added. Thus, you should be able to get to any field data that you might need from either without the added Relationship.
This also means that you should be able to replace your field_store_node.type IN ('lead') filter with a simple node.type filter after making this change without any need for the field_data_field_hotel.bundle = 'lead' stuff.
Comment #3
DigitalFrontiersMediaThe more I think about this, the more I think this isn't a bug but simply a problem with the Relationship that was added. Changing to Support Request and closing. Please re-open if this ends up not being the answer and if it, indeed, turns out that Views is somehow the culprit.
Comment #4
DigitalFrontiersMediaI stand corrected. I had missed the new node alias "field_store_node" on the join and was interpreting
as
As you say, there appears to be a problem here. Setting back to Active, Bug Report
Comment #5
Dave KopecekI"m opening this back up. Pretty sure this is a bug and not how a backreferences should work. Here's the gist of it:
When the base of a view is an entity of type "node" creating a Reverse reference in Views, i.e. something that reads like "Relationship "Content: Stores(s) (field_store) - reverse (to Content)" should return "content", i.e. nodes. It should not return "Users".
As currently constructed query blindly assumes that all entity_ids are NIDs. If the entity_type is type "user" entity id is a UID not a NID. If there is a Node where NID = uid-returned-from-view you'll get "extra" mis-related rows returned.
I'm now thinking that it's not the BUNDLE type, that's the issue, but the ENTITY type. The entity type should be specified as a condition in the join:
While I'm by no means an expert on the dark inner workings of these entity tables it would seem to me that one way to fix this programatically would be to make this be field_data_field_store.entity_type = entity-type-of- views-base-table. This would make the backreference work in the great majority of cases. It seems that a "multiple entity back reference" would require some tricky joins and might best be handled separately.
And another thing... This is probably another issue, but it looks like the view as constructed will also pick up deleted field references. After removing the field_store field from my user table in the above example, there are still rows in field_data_field_store with entity_type "user" left in field_data_field_store with the deleted column set to 1. While we're at it we should probably filter them out in the join as well:
Regarding #2 above:
I think you're mis-reading the query. It's created by Views and performs the joins correctly, it just isn't limiting the joins for multiple entity use cases.
Comment #6
Dave KopecekBased on implementations of hook_field_views_data_views_data_alter() found in the views module ( see views/modules/taxonomy.views.inc, etc) I think the solution here is pretty straightforward: add a 'join_extra' array to $data['node'][$pseudo_field_name]['relationship'] in node_reference_field_views_data_views_data_alter() as below.
This seems to work:
Will post a patch shortly.
Comment #7
Dave KopecekPatch for #6
Comment #9
Dave KopecekHmm, looks like patches created by TortoiseGit aren't liked. Let's try this again.
Comment #10
DigitalFrontiersMediaPatch failed to be re-tested due to incorrect status. Changing status to try to kickstart it again. Or does the patch need to be re-submitted?
Comment #12
Dave Kopecek#9: node_reference.patch queued for re-testing.
Comment #14
Dave Kopecek3rd time's a charm, I hope.
Comment #15
czigor CreditAttribution: czigor commentedThis works. Views itself has the same solution in #1321210: Join condition missing for Field API table(s) so this must be the right way to go.
Comment #16
Chris Matthews CreditAttribution: Chris Matthews commentedComment #17
renatogReally makes sense
Comment #19
renatogcommitted to the dev branch.
Thank you so much everyone