I'm interested in this module for a project, but I'm slightly put off by the use of views field view...

I'm wondering if there's a different way to accomplish this -- I'm pretty good at getting views handler and views data to do crazy things, if I say so myself :)

From what I can tell, there's currently:

- the outer view, which lists nodes and uses an argument to narrow this down to just the current node the user is viewing. This then uses a relationship via the product reference field on the node to get to the products. In doing so, it will multiply the result rows, so there is one result row per product entity referenced by the node. It embeds the inner view, passing the product_id as the argument.
- the inner view lists the recommender_similarity table. This takes as an argument an entity ID, which is the source_eid column in the table. It then uses a relationship on the target_eid column to jump to the Commerce Product base and from that to the Node base to get the product titles. (It adds filters by the recommender app, sorts by similarity, etc though that's by the by.)

The first, relatively minor thing that jumps out at me is that the outer view gets several products as rows, and then the inner view lists the recommended ones for each of those. That means you have lists in lists, which to the end users should be all one big list. That presumably means some clever theming has to happen to merge those sublists together?

As for the need for a view in a view, it seems to me that instead what's needed is a relationship that takes you from the product ID in the commerce product table to the source_eid in the recommender table. That will obviously multiply the rows again, but that's exactly what we want here:

- node ID
-- multiply rows to product IDs via referenced products
--- multiple rows to recommender items via source_eid

An extra relationship definition seems doable to me -- and while it would be a pretty big query with a lot of join, it's preferable to having views in views -- or have I missed something?

Comments

dwkitchen’s picture

Assigned: Unassigned » dwkitchen

Thanks for all the feedback on the module, keen to get it.

As briefly mentioned on IRC I had to write a views relationship handler for a project at work, so will either look at writing one for this module or patching the one in Recommender API so the recommendation source ID can come from a relationship as well as a contextual filter (argument)

joachim’s picture

I'm not sure you need a custom handler here.

Defining a relationship from {commerce_product}.product_id to {recommender}.source_id with the basic relationship handler should do it.

Now, you *could* add a custom handler in order to limit the relationship join on {recommender}.app_id. That would require a custom class.

dwkitchen’s picture

That's what I meant missed out the word definition somewhere

If needed bookmarking: http://drupal.org/node/260703#comment-4134520

joachim’s picture

The best place to look for a model of a relationship handler that limits on the join would be the user->profile2 relationship handler which limits on profile type. That's handled by entity_views_handler_relationship_by_bundle in entity module.

dwkitchen’s picture

Assigned: dwkitchen » Unassigned
Status: Active » Needs review
StatusFileSize
new5.68 KB

Joachim,

Here is something for you to try, I have written two views_relationship_handlers and are in the attached patch to recommender. These could form the basis for an improved method of views support for Recommender API.

I have added two pseudo fields to the Commerce Product in Commerce Rec and two revised view definitions in latest commit to Commerce Rec.

Would appreciate your feedback.

Thanks

David.

joachim’s picture

That looks very nifty; more complex than what I had in mind (which was a hack job :D), so much much more reusable! I really like the way this boils down to just being a relationship from one entity to another via the similarity.

A few points:

> 'source eid' => 'product_id',

I think it would be better to use the 'relationship field' definition item that the Views basic relationship handler provides, since that does the same thing. It means you have that waiting for you in $this->real_field, and it's clearer DX for people who implement this.

I'm completely baffled why you're joining to {recommender_app}:

    $join->definition = array(
      'table' => 'recommender_app',
      'field' => 'id',
      'left_table' => $this->first_join,
      'left_field' => 'app_id',
      'type' => !empty($this->options['required']) ? 'INNER' : 'LEFT',
    );

From what I can gather (and I may be wrong!) the {recommender_app} just stores a list of the different things that make use of the Recommender API. So it could well have only one row in it, ever, if we're the only module using the API.

Here's an updated patch that requires commerce_rec_views_data_alter() to switch to using 'relationship field' too. I've taken the liberty of adding some class docs, though I've not moved them to their own .inc files which will need doing too.

dwkitchen’s picture

Completely agree on the 'real_field' read about it after I had posted this.

The recommender_app is needed for the where condition

$this->query->add_where($this->relationship, $this->second_join . '.name', $def['recommender app']);

There might be more than one app installed so can't be sure on the app_id so need to filter on the app name.

The only limitation is the sort is hard coded - I would like to expose that in the normal sorting options so the user can pick.

joachim’s picture

> $this->query->add_where($this->relationship, $this->second_join . '.name', $def['recommender app']);

I'm having trouble decoding that, but wouldn't it be simpler to just do a standalone db_query() on the {recommender app} table and pull out the data you need for the join?

Or if the app_id is fixed once you've installed the module, sniff it when saving the handler options and save it in $handler->options, essentially as a hidden setting.

dwkitchen’s picture

Title: alternatives to view in a view? » Improve views support with Relationship handler
Project: Commerce Recommender » Recommender API
Version: 7.x-1.x-dev » 7.x-5.x-dev
Assigned: Unassigned » dwkitchen
Status: Needs review » Needs work

I am moving this over to Recommender API as it is where this issue should be.

Originally in the Commerce Recommender I had used Views in View to build up the relation ship as the Recommender API views integration didn't do what I needed.

Through working on a site I learnt more about Views and how to build a Views Relationship handler and this is what it needed in the Recommender API.

I am actually coming to the point of going live with the site it was for and would like to help with getting 7.x-5.0 released with improved views support.

Although this patch works for me it still needs some more work to make it more universal.

danithaca’s picture

@dwkitchen and @joachim: Thanks a lot. Will look into it soon.

danithaca’s picture

Status: Needs work » Closed (won't fix)

The new release 7.x-6.x should have fixed the problem. Release 7.x-5.x is not supported anymore. If you see the problem still present in 7.x-6.x, please reopen and change version to 7.x-6.x. Thanks.