GithubHelp home page GithubHelp logo

Comments (9)

jamescottrill avatar jamescottrill commented on July 28, 2024 3

This is actually a really key feature for me. We have exactly the same functionality where a user can be friends with another user. The problem comes because users can have posts, with either public, private, friend only or friend of friend access. I'm happy for my solution below to be completely wrong and for there to be a more concise way to do this, but this is how I'm getting around this at the moment.

type User {
    username: String!
    user_id: ID! @id
    posts: Post @relationship(type:"CREATED_BY", direction: IN)
    
}

type Post {
    id: ID! @id
    content: String!
    privacy: String!
    creator: User @relationship(type: "CREATED_BY", direction: OUT)
}

We want users to be able to view recent posts, so we need to be able to query the posts nodes and return all posts that the user is authorised to see. This means that we can't use the auth directive because querying all posts fails when a user isn't allowed to see all posts, so we're currently using the following:

extend type User {
    friend_in: User @relationship(type:"FRIENDS_WITH", direction: IN)
    friend_out: User @relationship(type:"FRIENDS_WITH", direction: OUT)
}
extend type Post @auth(
    rules: {
        operations: [READ],
        where: {
            OR:[
                { creator: { id: "$jwt.sub" } },
                { privacy: "public" },
                { AND:[
                    { privacy: "friends" },
                    { OR:[
                      { creator: { friend_in: { user_id: "$jwt.sub"} } },
                      { creator: { friend_out: { user_id: "$jwt.sub" } } }
                        ]}
                   ]},
                   ...
            ]
        }
    }
)

I've excluded the friends of friends part but it's an additional OR with 4 possible options
It also adds additional complexity to writing queries, here's one to get the posts of a user's friends

query{
  posts(where:{OR:[{owner:{friend_in:{user_id: "123"}}},{owner:{friend_out:{user_id: "123"}}}]}){
    id
    content 
    creator{
      username
      user_id
    }
  }
}

It seems unnecessarily complicated to manage when the ability to query in both directions exists. An alternative for us is to create the relationship in both directions, but that also seems to go against good practice.
If a relationship is defined as being in both directions then it seems that the assignment from one to another is arbitrary, so you could just assign it as (in)-[:REL]->(out).

from graphql.

darrellwarde avatar darrellwarde commented on July 28, 2024 1

why not, we generate methods to be used like this:

mutation{
  addUserAssociates(uuid:"id1", associates: ["id2", "id3"]) {name}
}

But what direction would that relationship be created in? From id2 to id3 or id3 to id2? Or literally both directions? 🤔

from graphql.

danstarns avatar danstarns commented on July 28, 2024

@Andy2003 Thanks for this. I presume relationships with "both" you would not be able to create?

from graphql.

Andy2003 avatar Andy2003 commented on July 28, 2024

why not, we generate methods to be used like this:

mutation{
  addUserAssociates(uuid:"id1", associates: ["id2", "id3"]) {name}
}

from graphql.

darrellwarde avatar darrellwarde commented on July 28, 2024

I may have been a bit liberal with the "wontfix" label, but I was going to close this as "won't do" for now - our target audience at present is for users coming in fresh with no existing data and using a GraphQL API to manipulate everything. Given that mutations for undirected relationships like this are a bit weird (you have to choose an arbitrary direction or create two relationships), I don't see this being too relevant for our target audience right now. But of course welcome a counterargument to that!

from graphql.

Andy2003 avatar Andy2003 commented on July 28, 2024

But what direction would that relationship be created in?

in java we generate this cypher

MATCH (from:User  {
	uuid: $fromUuid
})
MATCH (to:User)
WHERE to.uuid IN $toAssociates
MERGE (from)-[:ASSOCIATES_WITH]-(to)
WITH DISTINCT from AS addUserAssociates
RETURN addUserAssociates {
	.name
} AS addUserAssociates

but this is subject to be discussed. I would suggest that the node you start creating the relation is the start node. In The example above it would be the node with uuid id1.

from graphql.

darrellwarde avatar darrellwarde commented on July 28, 2024

Given that there is no way clearcut way to implement this, this will definitely be a post 1.0.0 feature if we do it all. We'll monitor whether or not if this is even a feature that users ask for and go from there. Will leave this issue open in the meantime!

from graphql.

morningcloud avatar morningcloud commented on July 28, 2024

Is there any plan to implement this feature? My use case also makes use of undirected relationship. In Cypher it is possible to have (n1)-[:REL]-(n2) for undirected relationship so I see the suggestion of @Andy2003 to introduce direction:BOTH then this can be interpreted to cypher by not including > nor < in either side

from graphql.

angrykoala avatar angrykoala commented on July 28, 2024

Hi all!, this rfc defines the proposal for undirected relationships, which is already a work in progress for the next release. The interface is slightly different to the proposals here, but should cover the requested use cases

from graphql.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.