Lets say i have the following types with n to n links:
type Cart {
id: ID!
items: [Item] @hasInverse(field: inCarts)
}
type Item {
id: ID!
inCarts: [Cart]
}
Now i have a defined list of ids of items.
Is it possible to find all carts which contain this exact list of items (or more) with a DQL query?
Sort of example query:
var(func: type(Item)) @filter(some filter) {
items as uid <-- the list of items
}
q(func: type(Cart)) @filter(filter to only fetch Carts with given list of items or more) {
uid
}
I think you’ve got to know the size of the list and do a query per item. For efficiency I’d come down from one of the items to start.
item1 as var(func:type(Item),first:1) @filter(..)
item2 as var(func:type(Item),first:1,offset:1) @filter(..)
item3 as var(func:type(Item),first:1,offset:2) @filter(..) {
carts as inCarts
@filter(
ge(count(items),3) and
uid_in(items,uid(item1)) and
uid_in(items,uid(item2))
)
}
carts(func:uid(carts)) { uid }
If you wanted a precise match you could match the exact length instead: eq(count(items),3)
I’m curious to see if anyone comes up with a dynamic way to do it. Some kind of “match all” function for query variables would be nice.
items as var(func:type(Item)) @filter(..)
carts(func:type(Cart))
@filter(all_uids_in(items,uid(items)))
{ uid }
Try to keep the ineficient type functions out of root as much as possible. The pagination will not produce the expected results here if pagination on all blocks like your example. If the intention of the blocks is to reduce the universe then at all possible start the next block with the smallest universe possible like for item2, use uid(item1) for the root
Given is a filter for Item.name called itemFilter. This filter results in n items → the amount of matching items is unknown, can be 0, can be 20. Lets call this list filteredItems.
What I want to query is the carts which contain filteredItems as a subset of Cart.items.