I'm not getting any sliders showing up at all. I traced the problem to the call to search_api_ranges_minmax() in _buildUISliderForm() in ./plugins/facetapi/widget_links.inc. This is used to calculate a min and max value to use for the slider. This always returns empty for both min and max, and therefor the slider doesn't display :

    // Query the min/max values for the range slider
    $min_value = search_api_ranges_minmax($variables, 'ASC');
    $max_value = search_api_ranges_minmax($variables, 'DESC');

    // Kill widget if there is nothing to do
    if (empty($min_value) && empty($max_value)) {
      return array();
    }

If I hack in a min and max the slider displays fine. So why is search_api_ranges_minmax returning empty.

My search index is on Commerce Product Display nodes, and I have added a field through to the Product Price. This is the field that I have the search range facet on.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

mrfelton’s picture

More tracing shows that search_api_ranges_minmax_execute returns no results. The result count is 50, yet the results array only has one item. I don't understand why its only returning 1 or the 50 results, even before any facets have been applied.

mrfelton’s picture

Status: Active » Needs review
FileSize
537 bytes

Attached patch get its semi working. With this applied, the slider displays and the min and max are correctly set. However, adjusting the slider seems to do nothing at all. The page reloads, but the search results look identical.

Also, the slider displays decimal numbers like 44.55 as 4455, which is completely wrong, bit that's another issue altogether.

Anonymous’s picture

Status: Needs review » Needs work

Thanks,

@#1 it should return only 1 value: the min or max value. We don't need anymore, so to reduce load I only query 1 value. It's unrelated to the # of values setting in the widget (I couldn't find a way to remove it).

@#2 For some reason, this patch actually breaks my sliders, which are working fine without the patch. So something "deeper" is going on here. Will have to figure out what and why...

Anonymous’s picture

>> Also, the slider displays decimal numbers like 44.55 as 4455, which is completely wrong, bit that's another issue altogether.

No, the value is actually rounded at the final step.

// We have to round because jQuery slider cannot handle decimals
return round($return);
Anonymous’s picture

>> If I hack in a min and max the slider displays fine. So why is search_api_ranges_minmax returning empty.

It may be returning empty if there are no results for your slider facet/field? Are you sure you have content indexed with values for the slider field?

mrfelton’s picture

@morningtime - very strange that the patch makes the slider work for me, but breaks yours. What version of search_api are you running with (I'm using 1.0-rc1). I understand about the query only returning one result now. That makes sense. There are definitely results for this indexed search. I have 50 products created with devel generate, and the query returns a query count of 50.

My index is being run on product display nodes, with a field relationship through Product through to Product Price.

I can see the last step where the rounding happens, however my cheapest product is $8.30, but the min range on my slider is $830. It the same with the high value.

Anonymous’s picture

Concerning round() rounding "$8.30" to 830. This can mean two problems: either your field is a textfield, or your raw value (in the database) is actually 830, not 8.30. Can you check the raw field?

I for example have sliders on a decimal price field, and a discount % field, both stored as decimals 0.0000, and see no issues. So far, nobody else using this module would need your patch.

mrfelton’s picture

The field is a commerce price field. The data in the database is indeed 830 rather than 8.30 - but that just seems to be how commerce stores it. I tried creating a brand new price field, and set the price to $8.41 (I literally typed 8.41), and that is stored in the database as 841. Seems to be standard commerce behavior. Commerce knows to display that as $8.41.

mrfelton’s picture

It's an int field at the db level.

CREATE TABLE `field_data_field_optics_price` (
  `entity_type` varchar(128) NOT NULL DEFAULT '' COMMENT 'The entity type this data is attached to',
  `bundle` varchar(128) NOT NULL DEFAULT '' COMMENT 'The field instance bundle to which this row belongs, used when deleting a field instance',
  `deleted` tinyint(4) NOT NULL DEFAULT '0' COMMENT 'A boolean indicating whether this data item has been deleted',
  `entity_id` int(10) unsigned NOT NULL COMMENT 'The entity id this data is attached to',
  `revision_id` int(10) unsigned DEFAULT NULL COMMENT 'The entity revision id this data is attached to, or NULL if the entity type is not versioned',
  `language` varchar(32) NOT NULL DEFAULT '' COMMENT 'The language for this data item.',
  `delta` int(10) unsigned NOT NULL COMMENT 'The sequence number for this data item, used for multi-value fields',
  `field_optics_price_amount` int(11) NOT NULL DEFAULT '0' COMMENT 'The price amount.',
  `field_optics_price_currency_code` varchar(32) NOT NULL COMMENT 'The currency code for the price.',
  `field_optics_price_data` longtext COMMENT 'A serialized array of additional price data.',
  PRIMARY KEY (`entity_type`,`entity_id`,`deleted`,`delta`,`language`),
  KEY `entity_type` (`entity_type`),
  KEY `bundle` (`bundle`),
  KEY `deleted` (`deleted`),
  KEY `entity_id` (`entity_id`),
  KEY `revision_id` (`revision_id`),
  KEY `language` (`language`),
  KEY `field_optics_price_currency_price` (`field_optics_price_amount`,`field_optics_price_currency_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Data storage for field 25 (field_optics_price)' |
Anonymous’s picture

Title: No slider displays - min/max calculation always returns nothing » Add support for Commerce module price fields
Category: bug » feature

Ok, that explains your values look like 830. I think the deal here is to add support for Commerce price fields. This requires:

- detect Commerce price fields
- auto-format field_xxx_price_amount before rounding (e.g. divide by 100)
-

In my case the $fields (on line 100 of search_api_ranges) looks like:

(
    [price_final] => Array
        (
            [type] => integer
            [value] => 3.0000
            [original_type] => decimal
        )

)

Can you check what your $fields outputs? (after $fields = search_api_extract_fields($wrapper, $fields);))

Anonymous’s picture

This could be difficult issue. The commerce fields are apparently stored as "830" instead of "8.30". This means the filter query should be ?f[0]=price:[830+TO+6000] would be price sfrom 8.30 to 60.00. That also requires a JavaScript detection of the commerce field. Because when changing the sliders it should post "8" as "800" to the browser.

I don't have time currently to figure all this out, but if you can come up with a patch I will review and apply it.

I think the easiest way to solve this, it by providing a custom entity property for commerce fields. So it becomes a separate field, with pre-formatted numbers.

Something like this inside a hook_property_info_alter()

...
  $properties['commerce_price_field'] = array(
    'type' => 'integer',
    'label' => t('Commerce price field'),
    'query callback' => 'entity_metadata_table_query',
    'getter callback' => 'custom_commerce_price_get_properties',
  );
...

The callback "custom_commerce_price_get_properties()" would read the commerce price field, format it (divide by 100), return an integer and allow Search API ranges to work effortlessly.

Need to find a way to do this automatically for each commerce price field though.

mrfelton’s picture

Cross posting #1198758: Search API integration as there is some relevant info there, though nothing that touches on this specific issue.

@morningtime - creating a separate field using hook_property_info_alter() as you suggested (if I'm understanding you correctly) seems to be a little overly complex perhaps? If you were to do this, presumably this would mean that you'd have to index that field, rather than the standard price field? Or am I misunderstanding - I've no experience with hook_property_info_alter(). Would it not be simpler for this module to detect if a the field was a commerce price field, and do the manipulation there and then, rather than creating a separate field just for this purpose? I don't really understand how a field created through hook_property_info_alter would affect the rest of the system either - would this field then become available for use in other places/contexts in the site?

Anonymous’s picture

If you were to do this, presumably this would mean that you'd have to index that field, rather than the standard price field

Yeah, that's my first idea. There should be an easier way... I guess you just need a new class for SearchApiRangesCommerceWidgetUISlider in widget_links.inc, and alter the html display formats. Difficulty remains the slider's input boxes, which would show a value of 100 for a $1 price.

Also I think the commerce price field is some kind of multi-value field / array? Then we still need a solution to just index the "100" integer price value.

Anonymous’s picture

Status: Needs work » Postponed

Postponing until Commerce fields can be indexed correctly by Search API.

Search API ranges only works for decimals/integers/floats, not for the dual-value price/currency of Commerce module. Also Commerce stores prices as "100" for "$1.00", so that's another problem I can't fix. Will need a "multiplier" effect in the Facet API settings.

Maciej Lukianski’s picture

This is actually even more complex.

The final price displayed to the user may not be the same as the one saved to db. Before the display, there is a whole layer for altering the final price. Commerce allows Rules to alter the price: taxes can be applied in between and other modules like discounts and else may alter the final price, so this is not just a matter of "divide by 100". We'd have to use some of the code from commerce_price_field_formatter_view() to get the final price and then build a search index and the search range on the result.

Workaround:
I used a separate decimal field for keeping the price indexed by Solr.

1. I created a decimal field. I created in on the display node, but it could be created on the product as well.
2. I created a rule, which keeps this field in sync with the product price.
3. I index the field instead of the the actual price field and this is what I put the range facet on.

All on-the-fly calculations commerce does will not be taken into account but if you have just one tax rate (my situation) and no other discounts, coupons etc, this can be used.

jsacksick’s picture

Status: Postponed » Needs review
FileSize
7.08 KB

To get it work, you have to follow the following steps :

1) Apply the patch coming from this issue #1518084: Expose a new property to Entity API (Amount floatted) in order to get a new property (the decimal amount), index this new field.

2) Apply the attached patch.

3) Clear the cache :p

4) Enable the search api ranges processor (under the workflow tab) + select your fresh new amount decimal field. Save your index, clear it & reindex.

5) You'll end up with a max and a min indexed for your amount used for the range sort and it should work !

frixos12’s picture

Hi.

In the forth step the processor doesn't show the decimal amount index field as an option to run on.

It doesnt validate this condition if (search_api_is_list_type($field['type']) && in_array(search_api_extract_inner_type($field['type']), $eligible_types)).

Have you tested yourself?

Thanks

jsacksick’s picture

Of course I tested it ... And this should work because :

$eligible_types = array('integer', 'decimal');
jsacksick’s picture

Is Your index on the node (Are you indexing the product displays ?), and is your product reference field multiple ?

frixos12’s picture

Yes i am indexing the product displays and my product reference field is not multiple.

zambrey’s picture

Yeah, it doesn't work for single reference fields.
Anyway, thanks for taking time to fix this issue.

jsacksick’s picture

This is supposed to work already for non multiple fields... This patch is for multiple fields ...

jsacksick’s picture

Without the processor...

Haza’s picture

Status: Needs review » Needs work

Applied the patch, followed the instructions, and, on the "status" tab of search_api

Notice: Undefined index: field_product:commerce_price:amount_float_asc in SearchApiDbService->indexItem() (line 332 of /.../commerce_kickstart/modules/contrib/search_api_db/service.inc).
(a lot of time)
Couldn't index items. Check the logs for details.

I'm using a db server.

khiminrm’s picture

#16 works for me for single value field without apllying the included patch.

drunken monkey’s picture

You can't add new fields in a processor, you'll have to use a data alteration for that.

jsacksick’s picture

If I remember well I first tried to use a data alteration for that but it wasn't possible... Maybe i should try again.

drunken monkey’s picture

If you run into problems with the data alteration, please just ask here. But it's definitely the way to go.

jsacksick’s picture

Status: Needs work » Needs review
FileSize
7.57 KB

This new patch uses now the hook_search_api_index_items_alter() instead of a processor/data alteration callback.
The only thing you need to do know is just reindex after submitting the facets form in SearchAPI UI.
After that, min and max fields will be added to your index for multiple values fields.
Some improvements can be done :
1) Add the min and max fields only for facets with slider range widget.
2) Remove added fields when non needed anymore.
3) Think about a solution for indexing the correct price (at least with the preacalculation rules).
4) I didn't use a data alteraion callback because I wanted to facilitate the user experience and do it automatically... (We may replace that later)
5) We may find a solution to reuse the agregation data alteration callback because the min and max agregation are available (Because it's not really simple/intuitive for the beginners).

jsacksick’s picture

Status: Needs review » Needs work

Doesn't work with search_api_db backend actually....

jsacksick’s picture

Status: Needs work » Needs review
FileSize
7.21 KB

Ok, so with the regular data alteration, this is working well. Once your multiple price field select in the ui, go under the workflow tab and choose the search api ranges data alteration for your field, reindex and this should work!

kotnik’s picture

Status: Needs review » Needs work
FileSize
7.21 KB

Small modification that sort of half-works.

Jsacksick, please take a look, tnx :)

kotnik’s picture

Status: Needs work » Needs review
FileSize
7.18 KB

configurationFormSubmit() result was overriden by it's parent. Removed that and the sorting now works.

kotnik’s picture

Fixed notice when index field is not set yet.

jsacksick’s picture

The last patch isn't ok, the field should be indexed automatically, right after checking the ranges alteration.
The difference between the agregation data alteration and that one is that we're adding fields in the configurationFormSubmit (And this is maybe happening too late).
If you dsm the form_state values in search_api_admin_index_workflow_submit, the values array for the ranges doesn't look like the expected array.
For instance when the aggregration callback is adding fields to the index, there's a field array in the values (sthg like)

<?php

'search_api_aggregation_1' => array(
'type' => ...
'name' => 
);

?>

And in the ranges form state values this looks like a string that contains the field name and also the field name as a value when checked which isn't correct.

kotnik’s picture

In case patch needs to be applied from drush makefile, it will not be possible with the one in #34 (since it changes .info file at the bottom).

Patch attached here is the same one as in #34, but the info file change has been moved up to enable easy patching.

Anonymous’s picture

I have tried patch from #36 and applied to my project. I do not use the commerce module, but I wanted to check if it caused issues with my regular project.

It seems to work fine. If one more person can confirm that patch #36 really works for your Commerce module, I will commit it.

Anonymous’s picture

Status: Needs review » Fixed

Status: Fixed » Closed (fixed)

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

tommygun86’s picture

this fix is included in 7.x-1.3 or in 7.x-1.x-dev ? because i've tried both versions with commerce 7.x-1.2 and it still showing 1,10 as 110

skatraga’s picture

Issue summary: View changes

I installed the latest Commerce Kickstart (as of April 2014). I still see the issue below and no sliders showing up:

Notice: Undefined index: field_product:commerce_price:amount_decimal in SearchApiRangesAlter->propertyInfo() (line 136 of /home1/sidpictu/public_html/profiles/commerce_kickstart/modules/contrib/search_api_ranges/includes/callback_search_api_ranges.inc).
Notice: Undefined index: field_product:commerce_price:amount_decimal in SearchApiRangesAlter->propertyInfo() (line 141 of /home1/sidpictu/public_html/profiles/commerce_kickstart/modules/contrib/search_api_ranges/includes/callback_search_api_ranges.inc).

Could someone help...
thanks
sid