Closed mkgn closed 6 years ago
Hi,
In terms of filters I think it would be good to create some hook which allows developers modify data before search so then developers will have unlimited flexibility (i.e. with using lodash library). I will think more about how to create such a interface.
If you also mean creating facets like that:
Development is quite complex, not sure if that is really needed for small datasets and I am afraid it can slow down the system (I can be wrong) but I am considering this in the future though
Btw Is it not a problem for you that ItemsJS works fast only up to 1000 items ?
ItemJS being able to handle ~1000 items is more than enough for small to medium projects. The suggestion was made because that will provide some completeness to the library in my opinion. As you have explained, I was thinking about some kind of a hook with a facet type (min/max) if specified at the time of initializing will fireup a function for the developers to do whatever they want.?
Initially can be some kind of a quick fix, before thinking about a full blown solution.
Yeah, that might be very useful and make it more complete. I think initially about something like this before making a real search:
itemsjs.prefilter(function(items) {
// make operations on items i.e. min / max using lodash
return items;
})
itemsjs.search()
or
itemsjs.search({
query: 'shoes',
prefilter: function(items) {
return items;
}
})
The second solution should be simplier as I guess there will be a few new lines of code and it's also quite flexible in terms of API changes in the future. What is your opinion ?
Hey, I've added the second solution to the code https://github.com/itemsapi/itemsjs/commit/c6578afa0e96768677b2889236d13435a7ec2ba5. Now it should be more customizable I hope
Great... let me play around and see. What I am trying to do is have a range slider to work with this
@mkgn I hope this problem is at least temporarily solved so I am closing this ticket. Thx for all feedback
Hello, I'm sorry for opening this ticket again, but I still don't understand how can prefilter function will help me to create a price range filter.
Can you please explain how can I link the prefilter with the configuration.aggregators filters in order to add the price range?
Thank you very much! Andrew
Hello Andrew,
You can use prefilter option for narrowing items based on price i.e.:
prefilter: function(items) {
return items.filter(item => {
if (item.price > 6) {
return true;
}
return false;
});
}
but it will not generate nice aggregation / facet ranges like in the example in the top. Number ranges are not supported right now.
If you want more powerful ranges you can try https://github.com/itemsapi/elasticitems (if you use Node.js) or Elasticsearch
Hello @cigolpl
Thank you very much for the info.
I manage to create a filter option with the prefilter function. https://gyazo.com/fb1658cf95ad25d77d598a21513e420e
Best Regards and thank you very much again for the help.
Wow, it looks really nice! Could I use your animation for a demo purposes ? (i.e. probably I'll convert to gif and include in documentation)
Thank you very much, Sure, you can include it in the documentation. I'm working on the design so I will have a better version soon enough.
Hi @cigolpl,
Here is an updated version of my demo if you still need it: https://www.dropbox.com/s/3vwocwoudbsz2p1/filter.mp4?dl=0
Here is the prefilter code I used to create the range filter
prefilter: function(items) {
var items = items.filter(product => {
if (product.price >= vm.minPrice && product.price <= vm.maxPrice) {
return product;
}
});
return items;
}
I also have few questions:
I'm using Vue Js on this project and I'm getting all data async using ajax and I used $(document).ajaxStop
to wait until all products are loaded, do you recommend a better way to do this?
It is possible to hide facets if there are only 0 or 1 buckets inside? I used v-if="buckets.length > 1"
but when I sort or apply filters, other filters will become inactive and they will be hidden automatically.
I want to make the aggregators something like this: https://gyazo.com/a868aeac2cb04d4f256233b78d76ebce
Kind Regards Andrew
Hello Andrew, thanks for your use case. The demo and its aesthetic design looks really amazing!
In terms of your question personally instead of .ajaxStop
I would use for specific ajax request (if this is what you mean):
$.ajax({
url: url,
success: function() {
alert('loading finished');
}
});
For ajax spinner I usually use sth like this:
$.ajaxSetup({
beforeSend:function() {
$('.ajax-loader').show();
},
complete:function() {
$('.ajax-loader').hide();
}
});
I am not so skilled in Vue but I think you can hide facets if there are 0 or 1. Not sure exactly how but I think you are close to the solution. Maybe using "v-show" or another logical conditions
Btw how is the sorting working in your demo - is it using fully itemsjs or making ajax request to the server ? It's a bit slowier when you click "best selling" than in the rest demo ;)
Thank you very much for the kind words about the design, for the big help and fast response. :)
The server responds with only 50 products per request and has multiple pages so I iterate through all pages and save all products in the allProducts
array. Here is an example:
var allProducts = []
var loadaAll = function(url, sortBy, totalProducts) {
var vm = this;
allProducts = [];
var productDeferreds = [];
var pageStartNum = 1;
for (var i = 0; i < totalProducts / 50; i++) {
var pageNumber = pageStartNum + i;
var $productRequest = $.get(url + '?sort_by=' + sortBy + '&page=' + pageNumber, function(response) {
allProducts.push.apply(allProducts, response.products);
});
productDeferreds.push($productRequest);
}
};
So this is how I get all products async and I'm using $(document).ajaxStop
to find out if all products are loaded.
Regarding the sort function, I'm using ItemsJs to sort by Title, Price (asc / desc) and Categories), for best-selling and featured I don't have access in the JSON so I have to set allProducts to empty and run the loadAll
function again with the proper sortBy
property and get all best-selling
or featured
products. I'm not sure if this is the best approach, it takes few seconds to load 500 - 1000 products.
Sounds good. In terms of sorting best-selling
and featured
maybe it would be better if you add fields to the json
best-selling
, featured
as true / false or 1 / 0 or "1" / "0" and then sort in the same way as by title
, price
, categories
. Not sure if it is possible in your case but it should be much faster than making requests to the server and reindexing
Is there a working solution for a range filter of analog values around? The links above are dead.
Hello @cigolpl ! when do you think this feature will be available on the packaged release?
as a workaround I've filtered the items before recreating a new instance. Not ideal but works in the short term.
const handleFilterChange = (values) => {
const filteredItems = applyRangeFilters(values, items);
const itemsjsInstance = ItemsJS(filteredItems, itemsJsConfig);
...
Hey @japo32, filtering through filter
function should be much better than recreating instance every time (you save re-indexing time):
var result = itemsjs.search({
filter: function(item) {
return item.rating >= 8 && item.reviews_count >= 200;
}
});
Hey @japo32, filtering through
filter
function should be much better than recreating instance every time (you save re-indexing time):var result = itemsjs.search({ filter: function(item) { return item.rating >= 8 && item.reviews_count >= 200; } });
Ok thanks. I've updated my code to use that.
Hi,
I would like to know whether it's possible to configure the library to filter for min-max value. For example, a list of items that has a price attribute where I can show a slider with a min/max value that gets filtered.
As of now it works great for item lists.