Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Collections #71

Closed
michaelbromley opened this issue Mar 1, 2019 · 5 comments
Closed

Collections #71

michaelbromley opened this issue Mar 1, 2019 · 5 comments
Labels
design 📐 This issue deals with high-level design of a feature @vendure/admin-ui @vendure/core
Projects

Comments

@michaelbromley
Copy link
Member

Relates to #43

See the last comment in the linked issue - we will rename ProductCategory to Collection to make it useful for other purposes.

What is a Collection?

A Collection is a grouping of Products. That is all.

What can a Collection be used for?

  • External Product categories i.e. shop navigation (which is why they will supercede that concept). Collections can be nested so suit well the concept of hierarchical categories of products e.g. electronics -> camera & photo -> lenses
  • Internal categories e.g. a group of products having the same supplier to which a promotion is being applied.
  • Grouping for any other reason such as conveniently finding products that are often changed.

How are Products added to a Collection?

Currently with the ProductCategory implementation, one or more FacetValues are assigned, and any matching Products can be considered part of the category. In actual fact, products are not really "assigned" to a category, the category merely defines the filter criteria and then the search feature is used to filter only those products with the matching FacetValues.

For collections, we could use the same approach but take it further by allowing a collection to define other criteria by which to filter products. This is what Shopify do with their collections.

So each Collection would have one or more Filters. A Filter is a function which defines user-configurable arguments and results in a method of filtering Products via the search query.

  • a FacetValueFilter would take one or more facetValueIds as the argument, and would then be able to filter by those ids.
  • a ProductNameFilter would take a comparator, "matches", "contains", "startsWith" etc. plus a string, and filter products based on their names.
  • etc.

These Filters can be composed together in a single Collection.

Collection nesting

When one Collection is nested in another, the Filters cascade from parent to child:

Collection "Electronics", filter: has "electronics" FacetValue
    |
    |- Collection "Exclusives", filter: product name contains "exclusive"

In the above example, the "Exclusives" collection would filter for any Product where the name contains "exclusive" and the Product has the "electronics" FacetValue.

Implementation

Much of the basic implementation can be directly used from the existing ProductCategory implementation. So first task is just to rename things.

I foresee two major challenges in designing the implementation of the above:

  1. How to define the Filter functions. We could look at using a similar pattern to the PromotionAction class, where the arguments are defined and then applied to the function in a type-safe manner, and also available via the API so the admin ui knows how to render the inputs.
  2. The actual relationship between a Collection and a Product in the database.
    • My initial thought is to have no relationship, and simply let Collections define a set of filter criteria which can be applied to a product search. To do this we need to ensure that each type of Filter has a corresponding field/fields in the SearchInput which can be used to apply those filter criteria to get the expected result set.
    • Another way would be to make a one-to-many relationship in the DB, and calculate this whenever a Collection is updated. However, this would also imply that any update to Product data requires all collection relations to be re-evaluated. This is a less elegant solution.
@michaelbromley michaelbromley added @vendure/core @vendure/admin-ui design 📐 This issue deals with high-level design of a feature labels Mar 1, 2019
@michaelbromley michaelbromley added this to To do in Beta Mar 1, 2019
@agustif
Copy link
Contributor

agustif commented Mar 3, 2019

I really like this implementation of collections you propose, hope to see it along in the beta.

Collections sound like smart categories to me, setup oncee and forget, just create product that fit those criteria, and can be used for a lot of things, like Brands, Destination, Provider, etc..

How can I help?

@michaelbromley
Copy link
Member Author

Collections sound like smart categories to me, setup oncee and forget, just create product that fit those criteria, and can be used for a lot of things, like Brands, Destination, Provider, etc..

Yep, that's exactly the intention.

How can I help?

I'm actually planning to work on this today. If you would like to contribute (not just to this issue, but in general) I propose we have a quick discussion about the best targets for contribution. At this early stage, I'm still occasionally making large refactors and therefore external contribution should be planned a little up front I think. If you like, we can do a call or a hangouts or whatever. Email me at contact [at] vendure.io 👍

@michaelbromley
Copy link
Member Author

Further thoughts on implementation

(in reference to point 2 of the implementation section in the original issue)

I think we will need a real one-to-many relationship in the DB, rather than just a set of filters which get dynamically applied. The filters approach would probably work fine when just used for product navigation, but will not work for the use-case of a Promotion which applies to a particular Collection.

e.g. a Promotion with the action "10% off all Products in the "Photo & Video" category. Whenever an Order is changed (item added/removed, quantity changed), all lines in the Order must be evaluated against all active promotions. Therefore we want to be able to run Promotion conditions and actions in a reasonably efficient manner.

Given this requirement, it seems a lookup table would be needed (i.e. "is productVariantId 1234 a member of collection 42?"). So creating a one-to-many relationship will give us this quick lookup capability.

The downside as mentioned initially is that now updates to Collections and Products/Variants becomes more complex:

  1. When updating a Collection and modifying the Filters in any way, all Filters should be evaluated and the new list of matching ProductVariants should be assigned to that Collection.
  2. When updating a Product of ProductVariant, we'll need to evaluate all Collections again, since the changes may have a) removed the Product from a Collection or b) added it to a Collection by reason of the collection Filter criteria.

Point 2. could get expensive. An optimization would be to limit the re-evaluation to those Collections with Filters which care about the changed properties of the Product. i.e. if we only update the title of the Product and nothing else, we need only re-evaluate those Collections which use the name-based Filter.

michaelbromley added a commit that referenced this issue Mar 5, 2019
Relates to #71. The entity itself has been renamed, but the resolvers have yet to be renamed.
michaelbromley added a commit that referenced this issue Mar 5, 2019
Relates to #71. Still to do: collection filter cascading, code clean up, more tests, UI polish
michaelbromley added a commit that referenced this issue Mar 7, 2019
@michaelbromley
Copy link
Member Author

Now implemented:

  • CollectionFilter mechanism
  • CollectionFilter based on facetValueIds
  • Cascading filters for nested Collections
  • e2e tests for the above
  • Admin UI for the above

To do:

  • String-matching CollectionFilter (e.g. "where name starts with 'foo'")
  • Manual CollectionFilter (select Product/Variants directly by ID)
  • Price-based CollectionFilter

@michaelbromley michaelbromley moved this from To do to In progress in Beta Apr 24, 2019
michaelbromley added a commit that referenced this issue Apr 25, 2019
@michaelbromley
Copy link
Member Author

Status update

Name filter

I have not implemented a filter based on ProductVariant name. Other filters will wait till post-beta and will have their own issues now.

Private Collections

The other major feature now added is that Collections can be private. This is useful for internal organization of the catalog which should not be exposed to customer, e.g. a Collection named "high profit margin" and used in promotions. This will work together well with #80 (to be done).

With these updates, this issue can be closed and any further extensions to Collections will get their own issues.

Beta automation moved this from In progress to Done Apr 25, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
design 📐 This issue deals with high-level design of a feature @vendure/admin-ui @vendure/core
Projects
No open projects
Beta
  
Done
Development

No branches or pull requests

2 participants