Sorting values when they come from different types

Hello there, i'm really new to ES, so please forgive me if this is a very basic question. I think it must be a trivial case, but i wasn't able to find a solution.

My problem is this: i have a list of products, and users from my website can add those products to their favorites list. The trouble i'm encountering is that when a user wants to see his favorites list, i need to sort the list based on "date added" to the list, but also be able to sort it based on properties from the products themselves (like Popular, New Products, Price, etc.)

So i have a 'Product' type, and a 'FavoriteItem' type. The 'FavoriteItem' has a property 'productId' which references the product, and a 'userId' property which references the user. It also has a 'dateAdded' property which would hold the date when the user added the product to the list.

None of the solutions i've considered are fully satisfactory to the problem i want to solve:

  • Having the 'FavoriteItem' type as an object type inside an array property of the 'Product' type: i think this is not recommended as there might be a lot of 'FavoriteItem' documents inside the same product, so ES would flatten them and i would lost their relationships. Also i'm not sure if i am able to filter the products based on the userId of the FavoriteItem documents, nor sort the products based on the 'dateAdded' property of them. Also, i want to keep the products list as clean as possible, avoiding to get it 'dirty' from foreign documents.

  • Having the 'FavoriteItem' type as a nested type of the 'Product' type: not considered as the favorite items can be added or removed any time.

  • Having the 'FavoriteItem' type as a child type of the parent 'Product' type: i think there is no way to sort the parent based on a child property yet, so i wouldn't be able to sort by the 'dateAdded' property of the 'FavoriteItem' child document.

  • Not having relationships between 'FavoriteItem' and 'Product' type at all: this is the solution i found more favorable until now. In order to retrieve the user's favorite list, I just simply execute a filter query on all the 'FavoriteItem' documents matching the userId, and sort them by 'dateAdded'. As the favorite list is paginated, i just simply get by n 'FavoriteItem' documents and then execute a multi-get query on the 'Product' type for those n items. However, doing things this way wouldn't allow me to sort on the products properties too, like price, or newest products. I wouldn't want to duplicate values on both documents, but i would be willing to do it if it was the best approach.

So, is there a better approach to my problem?

Thanks a lot

One other solution would be to have multiple different document "shapes", with each one solving a different requirement.

Hello Mark, thanks for your reply.

When you say having different document shapes, would it be something similar to what am i considering like having a FavoriteItem type and a Product type? If that is so, how could i retrieve a list of FavoriteItem documents sort by a property belonging to the 'Product' type? (e.g price, popularity, etc.)

Is that what you were referring to, or i totally misunderstood your suggestion?

Many thanks

Yep, but you need to do two different queries, you can't get them in one.

Thanks a lot for your help.

Finally, i ended up follwing the Parent/Child path:

My FavoriteItem type is now a child of the Product type.

Whenever i want to search the user favorites, i always perform a search on the FavoriteITem type, with a has_parent query to get the associated product id, which i use to get the product properties (i need to perform a mget query to get all the products in every favorite page, which i think it's not a big deal since every favorite page is 6 items length).

If i need to sort by a FavoriteItem property, i perform a regular sort operation.

If i need to sort by a Product property (aka. the FavoriteItem parent) , i use a function_score query as stated in the has_parent query reference, then i can sort by price, popularity, etc.

I can even perform a search on the products properties in the has_parent query, which is great as i needed that feature anyway.

I really hope this solution don't bite me back in terms of performance in the future :smile:

Thanks again