Developer forum

Forum » Development » Range price facet

Range price facet

Jose Caudevilla
Reply

Hi:

I have to implement a range price facet. This range has to contain the maximun and minimun price of a set of products.

For example , if i have a set of bikes the minimun is 100 and the maximun is 10000.

So if i want to get only the white bikes by a facet the minimun and maximun price must belong to the white bikes set.

Im trying to get this maximun and minimun using a BeforeQuery / AfterQuery but i get a StackOverFlowException in both notifications.

 

Here is the code of the notifications:

 

BeforeQueryNotification

namespace Cemevisa.Notifications
{
    [Dynamicweb.Extensibility.Notifications.Subscribe(Dynamicweb.Indexing.Notifications.Query.BeforeQuery)]
    public class BeforeQueryNotification : Dynamicweb.Extensibility.Notifications.NotificationSubscriber
    {

        public override void OnNotify(string notification, NotificationArgs args)
        {
            Dynamicweb.Indexing.Notifications.Query.BeforeQueryArgs beforeQueryArgs = args as Dynamicweb.Indexing.Notifications.Query.BeforeQueryArgs;

            if (args == null || !(args is Dynamicweb.Indexing.Notifications.Query.BeforeQueryArgs))
                return;

            QueryService queryService = new QueryService();

            
            IQueryResult queryResult = queryService.Query(beforeQueryArgs.Query, beforeQueryArgs.Settings);
            

            base.OnNotify(notification, args);
        }
    }
}

 

 

AfterQueryNotification

namespace Cemevisa.Notifications
{
    [Dynamicweb.Extensibility.Notifications.Subscribe(Dynamicweb.Indexing.Notifications.Query.AfterQuery)]
    public class AfterQueryNotification : Dynamicweb.Extensibility.Notifications.NotificationSubscriber
    {

        public override void OnNotify(string notification, NotificationArgs args)
        {
            Dynamicweb.Indexing.Notifications.Query.AfterQueryArgs afterQueryArgs = args as Dynamicweb.Indexing.Notifications.Query.AfterQueryArgs;

            if (args == null || !(args is Dynamicweb.Indexing.Notifications.Query.AfterQueryArgs))
                return;

            double max = 0.0, min= Double.MaxValue;


            //ejecutar la consulta para obtener los maximos y los minimos
            QueryService queryService = new QueryService();

            IQueryResult queryResult = queryService.Query(afterQueryArgs.Query, afterQueryArgs.Settings);

            IEnumerable<object> resultado = queryService.Query(afterQueryArgs.Query, afterQueryArgs.Settings).QueryResult;

            resultado.Count();

            if(resultado.Count() <= 1000)
            {
                foreach (var products in resultado)
                {
                   //get the maximun and minimun
                }
            }

            base.OnNotify(notification, args);
        }
    }
}

 

Is there another way to do this?

 

Jose, 

Regards.


Replies

 
Nuno Aguiar Dynamicweb Employee
Nuno Aguiar
Reply

Hi Jose,

 

How are you planing to render the range facet? In my mind a range can be achieved without any custom coding using manual index fields of type grouping  https://doc.dynamicweb.com/documentation-9/indexing/indexing-search/indexes#4785

 

This is a lot more efficient because it does no additional processing on query time. It basically becomes a new field with a value, behaving like any other facet. This means that you'll get a proper representation of ranges after you filter by "white".

 

Would that solve your issue?

 

Best Regards,

Nuno Aguiar

 
Jeppe Eriksson Agger Dynamicweb Employee
Jeppe Eriksson Agger
Reply
This post has been marked as an answer

Hi Jose,

The reason you're getting a StackOverflowException is because you're invoking QueryService.Query from inside the BeforeQuery. BeforeQuery and AfterQuery are both broadcast from QueryService.Query. That means that your subscriber will call QueryService.Query which will call your subscriber and so on. You need to break the cycle.

However, I don't quite understand why it's needed. Since 9.8.0, Dynamicweb gives you the option of indexing all product prices. In addition, numeric facets now provide minimum and maximum values. You can create a numeric facet on the price that you want to show, and that facet will give you tags for minimum and maximum values that you can use to render however you like.

- Jeppe

EDIT: Fixed mistype of version number from 9.7 to 9.8.

Votes for this answer: 1
 
Jose Caudevilla
Reply

Hi Nuno,

Here is the custom facet that im developing.

The custom facet is render by a jquery library.

This library render a bar so the user can select the price that want to filter.

I know your options is more efficient but i want that the users can select the price by themselves.

 

Thanks,

Jose

 
Jose Caudevilla
Reply

Hi Jepper:

 

My stagging version is 9.7.0.I didn't know that numeric facets provide minimun and maximun values, it will be all that i need to solve my problem.

I couldnĀ“t find how to get this values. How can i get this values please ?

 

Thanks,

 

Jose

 
Jeppe Eriksson Agger Dynamicweb Employee
Jeppe Eriksson Agger
Reply
This post has been marked as an answer

Hi Jose,

I made a mistype in my post. It's available from 9.8, not 9.7. Those two numbers are pretty close on the keyboard ;)

If you upgrade to 9.8, you can create a numeric facet and when rendering the facet, you can use the tags "Facet.MinimumValue" and "Facet.MaximumValue".

- Jeppe

Votes for this answer: 2
 
Nuno Aguiar Dynamicweb Employee
Nuno Aguiar
Reply

Hi Jeppe,

That's a great feature in 9.8. I did not know about it until now :)

 

Hi Jose,

It makes sense if you want to have a slider. Glad you found a simple solution with 9.8

 

BR,

Nuno

 
Lars Larsen
Lars Larsen
Reply

Hi Jeppe

I am using the Product catalog for Viewmodel and would like to get the minimum- and maximumvalues for a range facet. Aren't these properties available in the viewmodel? Can't seem to find them.

 
Lars Larsen
Lars Larsen
Reply

I now see that the numeric facet option values are sorted in FacetViewModel.Options. I therefore just get first and last value in the list as min. and max. values smiley

 
Jeppe Eriksson Agger Dynamicweb Employee
Jeppe Eriksson Agger
Reply
This post has been marked as an answer

Hi Lars,

It seems that these values weren't added to the FacetViewModel by accident.

I'm glad that you found a workaround, but I'll make an internal task to make them available so you don't have to rely on sort order.

- Jeppe

Votes for this answer: 1
 
Kristian Kirkholt Dynamicweb Employee
Kristian Kirkholt
Reply

Hi Lars

The Feature regarding Minimum and maximum values for FacetViewModel has been implemented in Dynamicweb version 9.8.4

This build is available in the download section

https://doc.dynamicweb.com/downloads/releases

Kind Regards
Dynamicweb Support
Kristian Kirkholt

 
Imar Spaanjaars Dynamicweb Employee
Imar Spaanjaars
Reply

We've been experimenting with the MaximumValue and MinimumValue and we do see the proper values. However, it seems to always be the min and max of all products in the index, not on the current result set. Is there an option to get min and max for the current filtered set of products?

Thanks!

Imar

 

 
Jeppe Eriksson Agger Dynamicweb Employee
Jeppe Eriksson Agger
Reply

Hi Imar,

This should not be the case. Only facet options that actually have hits in the current query result are considered in relation to minimum and maximum values. Do you by any chance have a notification subscriber, or other custom implementation, that filters the results after the index provides the result? It's currently the only thing I can think of that could produce this outcome.

- Jeppe

 
Imar Spaanjaars Dynamicweb Employee
Imar Spaanjaars
Reply

Thanks Jeppe. Upon further investigation, it turned out that the numbers were correct after all. However, we had the facet on the product price while the frontend was showing prices from the price matrix, so the min and max values didn't always line up with your expectations. Is there any guidance on what you said above: "Since 9.8.0, Dynamicweb gives you the option of indexing all product prices."? Since there can be many prices in the matrix, for different currencies and such, how would I set up the index and the range filter to get the proper results? (We're building a price range slider in this particular case and thus the min and max are important).

Thanks!

Imar

 
Jeppe Eriksson Agger Dynamicweb Employee
Jeppe Eriksson Agger
Reply
This post has been marked as an answer

Hi Imar,

There are a couple of ways to do that.

  1. Have a set of facets for each context that you want to use and have different Product Catalog paragraphs
  2. Create a facet group with facets for each price field you need. Then make them appear conditionally based on a query parameter

Of the two options, I believe 2) is the more robust one.

Assuming option 2), you could then send a unique context key (maybe "{languageid}_{currency code}") as a query parameter with every search, then have your price facets be shown conditionally based on the value of the context key. This allows you to hide and show facets depending on your context. The query parameter doesn't need to be used in the query. Also, you could split the standard product facets and price facets into different groups and separate the price facets for each context in their own facet groups which could make it easier to work with.

I hope that helps you to proceed. Otherwise, let me know.

- Jeppe

Votes for this answer: 1
 
Imar Spaanjaars Dynamicweb Employee
Imar Spaanjaars
Reply

Thanks, Jeppe. That's very helpful. The ball is in the customer's court for now but this will come in handy soon!

 
Ivan Marijanović
Ivan Marijanović
Reply

Hi Nuno

I am tryingto implement Price Range facet but link you shared in this response is no longer availble. 

Ivan

 
Imar Spaanjaars Dynamicweb Employee
Imar Spaanjaars
Reply

Maybe this helps? https://doc.dynamicweb.com/documentation-9/how-tos/general/implementing-a-pricerange-query

 
Stephen Jackson
Reply

Where are the Facet.MinimumValue and Facet.MaximumValue's accessed?

I tried implementing these, but they dont exist in the facet viewmodel. Have tried Number, Tags, Range, you name it... dont get those attributes in model.

 

Cheers

 
Nicolai Pedersen Dynamicweb Employee
Nicolai Pedersen
Reply

Hi Stephen

They are  present here: 
https://doc.dynamicweb.com/apix/api/Dynamicweb.Ecommerce.ProductCatalog.FacetViewModel.html#Dynamicweb_Ecommerce_ProductCatalog_FacetViewModel_MaximumFacetValue

Which version of DW are you on?

And can you share a bit of your code?

Thanks, Nicolai

 
Stephen Jackson
Reply

Thanks Nicolai. That helped a lot. 

I am currently editing directly in a cloned version of the facets selector, but I should ideally move this party locally to VS with the Nuget apackages installed. Then I wont end up asking silly questions in here...hehe

I am looking to do the same as people in this forum, and I selected Range first, thinking it might magically split the facet into a number of ranges, but I guess this is something one has to do themselves in the template?  

 
Nicolai Pedersen Dynamicweb Employee
Nicolai Pedersen
Reply

Hi Stephen

It depends on your context. Are you using Swift? Or is it a custom razor implementation? Or maybe even headless implementation?

The answer might be different based on that. Swift does not currently support range facets out of the box - so you have to do template chanes.

You can use a Grouped field instead: https://doc.dynamicweb.com/documentation-9/repositories/indexing/custom-fields#4785 - that would be setup and will work with checkbox facets. And it is more user friendly and works better on mobile.

BR Nicolai

 
Stephen Jackson
Reply

Ah thanks! Thats exactly what I need yes! I was gonna start implementing my own clickable ranges based on the max and in values... would have been very unnessacary

 
Stephen Jackson
Reply

I added a grouped field with type system.int32, and re-built the index, added the checkbox facet using it.

The values range from 0-3000 in the source column and I split it into groups of 0-500 501-1000 1001-3000 for example

But the checkbox value sin the template (3 groups correct), give crazy values (one is a huge negative value and two huge positive values)

Have I configured a datatype incorectly?  The source column is integer

 
Nicolai Pedersen Dynamicweb Employee
Nicolai Pedersen
Reply

Yes - change it to a system.string field and re-index. Then you should be home free.

 
Stephen Jackson
Reply

Thanks Nicolai

That did the trick.  

Filters the ranges nicely.

Only annoying thing is that I would like the facets that no longer apply, to still be shown after filtering with another one.

For example, if I click 1-500, all the other ranges disappear, but I have set it up as array so i can do multiple checkboxes... 

How do I set it so facet values are always present regardless of what is selected/filtered?

 
Stephen Jackson
Reply

Sorry I have to bump this. I am guessing people are on holiday now, but will bump just in case it was overseen for another reason.

The filtering is working fine now, but I would like all the range facets to show (in fact I would like all the facets to show) even when the filtering would exclude them. For example that they show in grey or something with 0 results showed.  Is this possible with the standard features or do I need to do something custom?

Cheers

//Steve

 
Nicolai Pedersen Dynamicweb Employee
Nicolai Pedersen
Reply

Can you show how your query (including the parameter) and your facet is setup for this particular facet?

Thanks, Nicolai

 
Stephen Jackson
Reply

Sure.

Attached screenshots of the index, query and facet definitions

 

 

index.png
 
Stephen Jackson
Reply

Query

query.png
 
Stephen Jackson
Reply

Facets

facets.png
 
Stephen Jackson
Reply

Sorry It was only possible to attach one file at a time, hence all the posts

 
Nicolai Pedersen Dynamicweb Employee
Nicolai Pedersen
Reply

Looks correct

Then it is probably your template. How does your facet template code look like?

 
Jeppe Eriksson Agger Dynamicweb Employee
Jeppe Eriksson Agger
Reply
This post has been marked as an answer

Hi all,

Facet options with no result are removed unless you tell the product catalog to keep them.

Try this:

- Jeppe

Votes for this answer: 1
 
Stephen Jackson
Reply

OMG Thanks, Jeppe! Jeg må være helt blind!  I was looking in the Facets module options and at the query logic etc! Dunno why I didnt check the proc catalog app

Now that it is working though I have the issue of the query being a logical AND on all fields, and if a user selects ONLY a term with 0 results one of these multiselect fields , a page with "We did not find anything matching your search result", will be shown, with the facets bar gone (so no option to clear filters and I have to close and reload page, or remove some of the query params in the address field). How do I avoid that, or configure the facets bar to ALWAYS show even if the returned results are 0?

Or is it bug that the facets are not shown then? Because they should basically be empty, but according to the setting, shown regardless?

 
Nicolai Pedersen Dynamicweb Employee
Nicolai Pedersen
Reply

Hi Stephen

I am affraid that is not your issue - the mentioned checkbox. It is correct that when you set it, you see all options with 0 - but that is not the issue at hand.

I have setup a simple example here: https://swiftdemo.dynamicweb-cms.com/components - it uses the prices for a grouped field. And the same facet in another group here: https://swiftdemo.dynamicweb-cms.com/clothing

In the clothing group, there are no products with a price higher than 100. So if you set that checkbox, this is what you will get:

You can see 2 options with 0 in them - you rarely want that.

You want it like this - only showing options that has results:

Now go to components group without that checkbox set, you will see this:

Showing 3 different price groups - only the ones with products in them. Still without the 0-checkbox set.

When you start checking options, they will not change what is available in the options - only the products in the search result:

So - my point is, that is not the checkbox that is your issue. It is either your template or your setup.... You can provide a URL and we can have a look.

BR Nicolai

 
Nicolai Pedersen Dynamicweb Employee
Nicolai Pedersen
Reply

And my setup:

The field

The parameter

The expression

The facet

 
Nicolai Pedersen Dynamicweb Employee
Nicolai Pedersen
Reply

I think your issue is that your expression group is of type "OR" and not "AND"

 
Stephen Jackson
Reply

Hei Nicolai.  It was only OR when I screenshotted it (I was experimenting). It is AND at the moment.

I can send you a link yes.

Would prefer not to post the link in a public forum though, as this is a work in progress for a customer. Do you have a mail address?

//Steve

 

 
Nicolai Pedersen Dynamicweb Employee
Nicolai Pedersen
Reply

Either post it here - otherwise you have to contact care@dynamicweb.dk to help you out.

Thank you for your understanding, Nicolai

 
Stephen Jackson
Reply

Ok thats fine. I will have to send it to the support address then

Thanks!

 

//Steve

 
Stephen Jackson
Reply

One more thing. In the docs, there is a property FacetGroupType

https://doc.dynamicweb.com/apix/api/Dynamicweb.Ecommerce.ProductCatalog.FacetGroupViewModel.html

which would be the logical choice to use for deciding the style to render a certain facet group, but I cannot find this property in the standard admin gui.

Are there properties which are available in the API but not implemented in the admin gui?

Thanks

//Steve

 
Nicolai Pedersen Dynamicweb Employee
Nicolai Pedersen
Reply

FacetGroupType seems to be a dead property that does nothing.

The FacetGroup has a list of FacetViewModel - and that will contain the information about how to render it.

  • Group (just a placeholder)
    • Facet (i.e. "Colors" or "Horse power")
      • Options (i.e. "Small, Medium, Large" or "<100hk, 100-200hk" etc.)

The "Facet" above, is the FacetViewModel which contains the RenderType property - that can be set from the UI.

BR Nicolai

 

You must be logged in to post in the forum