is there a way to setup a has_many: through type r...
# prisma-whats-new
m
is there a way to setup a has_many: through type relation?
a
@mike.johnson What kind of relation are you modelling?
m
Something like a user that purchases products.
I can't just use a relation on user > products because I need to keep track of created_at, and would like to have extra data
like "show me all purchases today" which has a user_id, and a product_id
a
Then you need an extra type
m
in rails it would be user has_many :products, through: :purchases
and purchases would be a join table with user_id and product_id fields
so if I make a purchase type, how do I relate both the user and the product to the purchase?
a
Here it would be a purchases Type, with two 1-many relationships to user and products
Same as a normal join table would be
m
right, when I did that I was getting the automutations to only populate one side or the other
ie: addPurchaseToUser mutation, but wouldn't add the product
Should I just avoid the auto-generated mutations?
a
You can do a nested mutation
m
right, ok I see that
think that will work out fine
now that I also have a purchases type, how can I order the products by number of purchases?
a
Copy code
mutation{
  createPurchase(productId: $productId, userId: $userId, paymentMethod: "CC")
}
Something like that for registering the purchase
m
yeah, so just dont use the addToUserPurchases auto-generated stuff?
a
No, they make more sense for direct relationships
And querying for the count would be something like:
Copy code
query{
  allProducts
  {
    name
    _purchasesMeta
    {
      count
    }
  }
}
m
_purchasesMeta?
a
Only you can't order by that yet
yes, every related collection has a corresponding meta object
m
sweet!
a
that contains aggregations
in this case, only count
m
so then I could get all products, get the counts and IDs back then order them in the front end
If there are many hundred products, is it better to do one query fetching all with fields like name, rating, etc or do an all query with only IDs, order them in front end, then do another query to get the top 10 products with all the real data I need?
a
That depends on a lot of things
There's paging support
But not with client side ordering
m
but how can it page if it can't order by relation count?
right
a
Depends on what you need
If you need the top 10, then get minimal data to determine that top 10, and query those
If you need all data anyways in the client, but it's just about sorting, then just get the data
m
so two smaller queries is better than a large aggregate query
from current analytics usually people don't go past the top 30 ish
a
Smaller queries would allow for better performance
m
then they will just search for the thing they want
so I wouldnt need to browse all 500 at once
a
Look into Algolia for searching
m
oh, it's just search by product tile
you helped me with the name contains last week 🙂
a
Ah, didn't remember, sry...
m
no worries, do you work for graphcool?
a
Nope
m
they should be paying you 🙂
a
Just a community member
m
thanks for all the help
a
No worries, glad to help
m
Seems like most all use cases have been figured out by now. I only have one more query that Im not sure if it's possible, it was a pain in sql too
a
Do tell 🙂
m
give me the top 10 products ordered by purchases that belong to users who have purchased THIS item
a
I was actually thinking about something else
For your previous orderby
that you need here too
You can create a SSS on the Purchase type
That increases a timesPurchased integer field on Product
m
interesting, so you can run a mutation as a function of another mutation? I have only read about external integrations, like send email on user create, but yeah, that makes sense
a
Yes, a server side subscription on
CREATE
of
Purchase
that will update
Product
to do
numberofPurchases++
m
how do I call the mutation from the inline module.export function?
a
using isomorphic-fetch
There must be something in the examples
m
console.log(event) doesn't seem to be triggering, where would this show up?
a
Your query should look like this in the end by the way:
Copy code
query ($productId: ID!) {
  allProducts(
    orderBy:timesPurchased_DESC, 
    first:10,
  	filter: { 
      purchases_some: { 
        user: { 
          purchases_some: {
            product: { id: $productId}
          }
        }
      }
    })
  {
    name
  }
}
In the event log of the server side subscription
m
ah, so NOT the console ?
a
No
It's executed server-side
In fullscreen mode, you can do a test run, and then the results show up on the right, in the log panel
m
see it when I hit test, but not if I run a real mutation
a
Then you have can click the button in the overview to show logs
m
oh that's super sneaky
a
Well, the header says 'LOGS'
😉
m
lol who reads headers
with a SSS how can you tell if it's a create or a delete?
a
Custom functions don't, it's a bug 😄
m
looks like it's just passing updated_at, Im not seeing a way to access the type of mutation
I could need to remove a purchase when a user returns an item
a
That;s your mutation_in filter on the left
Where it now says created, deleted
m
oh, so just setup two different SSS, one for create, one for delete
a
yep
m
i was trying to do it in the inline function, got it.
a
You can also include
mutation
in your subscription query
then you get a mutation field in your context.data.[Type] that says 'created', 'updated' or 'deleted'
m
nice! though unless I run out of space on the functions the first way is super simple
a
can't follow...
You mean 2 seperate SSS is better than checking the value of the mutation field
m
oh, just saying making two SSS is easier and clean way to do it
a
Got it. And yes, I agree
Although
itemPurchased+= context.data.Purchase.mutation == 'CREATED' ? 1 : -1
is also nice 🙂
There's actually an easier way to do this, but then you need to put the updateProduct mutation in the client
m
yeah, but then I might worry about forgetting to update, right?
a
true
m
on the updateProduct mutation, how do I get the current value of the productPurchasesCount so I can increment it?
a
two ways, the nice way and the hack way
Good way: query product first in the SSS, then do the update