vuestorefront / storefront-query-builder

ElasticSearch Query builder from the abstract "SearchQuery" object used by storefront-api, vue-storefront-api and vue-storefront projects
MIT License
7 stars 21 forks source link

Add `or`, `nor` filters to make more complex search queries #4

Closed cewald closed 4 years ago

cewald commented 4 years ago

Right now the opportunities to create a query are quiet limited. I now added support for filters containing or, or-not and not-in to the elasticsearch lib.

So you can filter queries like the following using the query-builder:

query.applyFilter({ key: 'visibility', value: { in: [1, 2, 3] } })
query.applyFilter({ key: 'status', value: { nin: 1 } })
query.applyFilter({ key: 'status', value: { nin: [ 0, 1 ] } })
query.applyFilter({ key: 'price', value: { orGte: 14.99 } })
query.applyFilter({ key: 'special_price', value: { orLte: 20.99 } })
query.applyFilter({ key: 'color', value: { or: [ 12, 14 ] } })
query.applyFilter({ key: 'size', value: { nin: null } })
query.applyFilter({ key: 'sku', value: { nin: [ 'XXX-XXX-1', 'XXX-XXX-2' ] } })

WDYT, is this something that would be handy?

gibkigonzo commented 4 years ago

@cewald @pkarw I'm thinking about mix this with https://github.com/DivanteLtd/storefront-query-builder/pull/3 Whole idea is that applyFilter should modify query based on filter from value. Can we have object with {filter: function} where every function returns queryChain? Same like here https://github.com/DivanteLtd/storefront-query-builder/pull/3/files#diff-13d602f7d04113162fedf4dd7b32f52bR13 So we can refactor this to:

const baseFilters = {
  gt: ({ attribute, value }) => queryChain.filter('range', attribute, value)
  ...
}

Its same typing like:

    customFilters?: {
        [key: string]: Function;
    };

So we can have object with base filters and custom. Then we can merge filters = Object.assign({}, baseFilters, customFilter || {})

and when we have all those filters we can just make a loop:

for (let filterKey in filters) {
  queryChain = filters[filterKey]({ attribute, value, config })
}

Whats we get? We can decouple applying filters logic. Which can gives us more readability (right now there are to much if and lets imagine that we want to add next filters).

cewald commented 4 years ago

@cewald @pkarw This is a really good idea. I agree with the too complex structure inside buildQueryBodyFromSearchQuery method.

I can try to add this if you like. So I would try to consolidate the changes of #3 and this PR (#4) into a refactored version with a modular ES query building.

Anyway, I was going to suggest a modification to add a applySort method to handle more complex sorting as well. – If we me make changes like you suggested, it would be much easier to apply these additions.

gibkigonzo commented 4 years ago

Great! :) It would be great if you can do this. That is exactly why we need to decouple apply filters logic if we want to extend this in future, like adding applySort

cewald commented 4 years ago

I will close this in favour of #6