Correct query visibility conditions Anybody help posts get

MATCH (u:User {publicId: '${data.userId}'})
OPTIONAL MATCH (follower)-[:FOLLOWS]->(u)
OPTIONAL MATCH (post)-[:HAS_CONTENT]->(content:PostContent)
WHERE post.userId IN [follower.publicId, u.publicId]
MATCH (postUser:User {publicId: post.userId})

OPTIONAL MATCH (post)-[:TAG_IN]->(taggedUser:User)
OPTIONAL MATCH (post)-[:SHOULD_SEE]-(specific:User)
WITH post, content, postUser,
     COLLECT(DISTINCT taggedUser) AS taggedUsers,
     COLLECT(DISTINCT specific) AS specificUsers,
     COLLECT(DISTINCT follower) AS followers
WITH post, content, postUser, taggedUsers, specificUsers, followers,
     { 
       post: post, 
       content: content, 
       taggedUsers: taggedUsers,
       specificUsers: specificUsers, 
       user: postUser,  
       follower: followers
     } AS postDetails
WITH COLLECT(DISTINCT { 
       post: post, 
       content: content, 
       taggedUsers: taggedUsers,
       specificUsers: specificUsers, 
       user: postUser
     }) AS filteredPostsstrong text
WITH [p IN filteredPosts WHERE 
      p.post.visibility <> 'onlyme' OR 
      (p.post.visibility = 'onlyme' AND p.user.publicId = '${data.userId}')] AS finalPosts
RETURN finalPosts;                                                         visibility wise post show public onlyme specific followers

What is your question?

1 Like

Just a comment, it looks like you are relating posts to their user by a user id stored on the post. You should not do that. You should have a relationship between the two nodes so you easily get them. You are doing a join-like search each time, which is not very “graphy”, but more like a relational db.

Also, why the optional matches? You use the values from those matches, so the query is not going to proceed anyway when no match is found.

Finally, your chaining of uncorrelated matches causes Cartesian products. I suggest you use a “collect subquery” instead.

1 Like

my question module.exports.createPost = async (userId, data) => {
const session = driver.session();

try {
console.log("data", data);
const randomId = Math.floor(Math.random() * 500 + 1);
const generator = UUID(randomId);
let id = generator.uuid();
const description = data.description
? data.description.slice(0, 1500).trim().replace(/'/g, "\'")
: "";

const visibility = data.visibility || "public";
let visibilityQuery = "";

if (visibility == "followers") {
  visibilityQuery = `
   MATCH (follower:User)-[:FOLLOWS]->(u:User {publicId:'${userId}'})

  `;
} else if (visibility === "specific") {
  const specific = data.specific || [];
  visibilityQuery = `
    MATCH (targetUser:User) WHERE targetUser.publicId IN ${JSON.stringify(
      specific
    )}
    WITH targetUser, u,post

    MERGE (targetUser)-[:SHOULD_SEE]->(post)
    WITH  u,post
    MERGE (u)-[:SHOULD_SEE]->(post)
  `;
} else if (visibility === "onlyme") {
  visibilityQuery = `
    MATCH (u:User)-[:POSTED]->(post) WHERE u.publicId='${userId}'
    MERGE (u)-[:SHOULD_SEE]->(post)
  `;
}

const contentArray = data.content || [];
let imageQueries = "";

contentArray.forEach((content, index) => {
  const imageQuery = `
    MERGE (pc${index}:PostContent {
      image: '${content.file}',
      postId: '${id}',
      mimeType: '${content.mimeType}'
    })
    MERGE (post)-[:HAS_CONTENT]->(pc${index})
  `;
  imageQueries += imageQuery;
});

const deletedAtQuery =
  data.deletedAt !== undefined ? `, deletedAt: ${data.deletedAt}` : "";

const query = `
  MATCH (u:User{publicId:'${userId}'})
  MERGE (post:Post {
    userId: '${userId}',
    postId: '${id}',
    description: '${description}',
    createdAt: datetime()${deletedAtQuery},
    visibility: '${data.visibility}'
  })
  with u,post
  MERGE (u)-[:POSTED {status:'${data.visibility}'}]->(post)
  WITH u, post
  ${visibilityQuery}
  ${imageQueries}
  RETURN post;
`;

const result = await session.run(query);
// console.log("result Result:", result);

if (result.records && result.records.length > 0) {
  return result.records[0].get("post").properties;
} else {
  return false;
}

} catch (error) {
console.error("Error creating post:", error);
return false;
} finally {
await session.close();
}
}; this condition wise getposts query

How to get Posts onlyme followers specific users and public

There is too much info. Let's break it down and resolve pieces at a time. I see from your visualization of your data that you do have relationships between entities. You should use these in your query and not join via 'id' values.

Let's start by defining your data model. Does this look accurate? Can a Post have multiple related PostContent nodes, or just one?

Using the diagram, can you describe what information you want to return?

From your first post, it looks like you want to do something like this:

  1. find a User by a 'userId' passed as a query parameter
  2. find all the User's followers (which are other Users)
  3. find all the posts of the User and of each follower
  4. for each Post, find the User that posted, the tagged users of the Post, and the Users that should see the post
  5. for each Post, collect all the Users tagged in the Post, collect all the Users who should see the post, and collect all the followers (Users) of the User that posted the Post.

Is any of this correct?

above diagram correct

const query = `
MATCH (me:User {publicId: '${data.userId}'})
OPTIONAL MATCH (me)-[:POSTED]->(mine:Post)-[:HAS_CONTENT]->(mineContent:PostContent)
OPTIONAL MATCH (userInfo:User {publicId: mine.userId})-[:POSTED]->(mine)
OPTIONAL MATCH (user:User)-[:POSTED]->(publicPost:Post {visibility: 'public'})-[:HAS_CONTENT]->(publicContent:PostContent)
OPTIONAL MATCH (me)-[:FOLLOWS]->(follower:User)-[:POSTED]->(followerPost:Post)-[:HAS_CONTENT]->(followerContent:PostContent)

OPTIONAL MATCH (mine)-[:TAG_IN]->(mineTags:User)
OPTIONAL MATCH (publicPost)-[:TAG_IN]->(publicPostTags:User)
OPTIONAL MATCH (followerPost)-[:TAG_IN]->(followerPostTags:User)

WITH me, 
     COLLECT(DISTINCT {post: mine, content: mineContent, creator: userInfo, tags: mineTags}) + 
     COLLECT(DISTINCT {post: publicPost, content: publicContent, creator: user, tags: publicPostTags}) + 
     COLLECT(DISTINCT {post: followerPost, content: followerContent, creator: follower, tags: followerPostTags}) AS posts

UNWIND posts AS postInfo

WITH me, postInfo.post AS post, postInfo.content AS content, postInfo.creator AS creator, postInfo.tags AS taggedUsers

WITH me, post, content, creator, taggedUsers,
     CASE 
         WHEN post.visibility = 'onlyme' AND post.userId = me.publicId THEN true
         WHEN post.visibility = 'specific' AND post.userId = me.publicId THEN true
         WHEN post.visibility = 'followers' OR post.visibility = 'public' THEN true
         ELSE false
     END AS canSeePost

WHERE canSeePost OR canSeePost IS NULL  

RETURN 
COLLECT(DISTINCT {post: post, content: content, user: creator, taggedUsers: taggedUsers}) AS posts           
 SKIP ${data.offset}
LIMIT ${data.limit};

`;
how to sort this query because response time 56second and this quer limit not work

{
"results": [
{
"post": {
"visibility": "public",
"description": "Description1",
"postId": "9831196306686243",
"userId": "1005055351656459"
},
"content": [
{
"image": "image.png",
"postId": "9831196306686243",
"mimeType": "image/jpeg"
}
],
"taggedUsers": ,
"specificUsers": ,
"user": {
"image": "image12",
"createdAt": "Wed Jan 17 2024 18:22:07 GMT+0530 (India Standard Time)",
"name": "user12",
"bio": "bio12",
"isPrivate": "FALSE",
"email": "a1@gmail.com12",
"authId": "cQdQNPFVUfMIhbODaZvUSFj3qm21",
"publicId": "1005055351656459"
}
},
{},
{}

] this type response