skip to Main Content

I’m developing a React Native app and utilizing Appwrite for storage and API calls.

For saving the user ID of users who like a post, I’m employing the following API call:

export async function likeVideoPost(postId, userId) {
  try {
    const posts = await databases.listDocuments(
      appwriteConfig.databaseId,
      appwriteConfig.videoCollectionId,
      [Query.equal("$id", postId)]
    );
    if (!posts) throw new Error("Something went wrong [post]");
    // Extracting the document from the JSON object
    const postDocument = posts.documents[0];

    // Extracting the existing likebyusers array from the post document
    const existingLikeByUsers = postDocument.likebyusers;
    const result = await getCurrentUser();
    const updatedLikeByUsers = [...existingLikeByUsers, result];
    
    const updatedPost = await databases.updateDocument(
      appwriteConfig.databaseId,
      appwriteConfig.videoCollectionId,
      [postId],
      {
        likebyusers: updatedLikeByUsers,
      }
    );
    return updatedPost;
  } catch (error) {
    throw new Error(error);
  }
}

here the respnse i recieved:

{
  "$collectionId": "xxx",
  "$createdAt": "2024-04-22T16:03:18.362+00:00",
  "$databaseId": "xxx",
  "$id": "xxx",
  "$permissions": [
    "read("user:xxx")",
    "update("user:xxx")",
    "delete("user:xxx")"
  ],
  "$updatedAt": "2024-04-22T17:40:05.047+00:00",
  "creator": {
    "$collectionId": "xxx",
    "$createdAt": "2024-04-22T16:02:44.297+00:00",
    "$databaseId": "xxx",
    "$id": "66268a2447ea7ce4f6b3",
    "$permissions": [],
    "$updatedAt": "2024-04-22T16:02:44.297+00:00",
    "accountId": "xxx",
    "avatar": "https://cloud.appwrite.io/v1/avatars/initials?name=Test&project=xxx",
    "email": "xxx",
    "password": "xxx",
    "username": "Test",
    "videos": [[Object], [Object]]
  },
  "likebyusers": [
    {
      "$collectionId": "xxx",
      "$createdAt": "2024-04-22T16:02:44.297+00:00",
      "$databaseId": "xxx",
      "$id": "xxx",
      "$permissions": [Array],
      "$updatedAt": "2024-04-22T16:02:44.297+00:00",
      "accountId": "xxx",
      "avatar": "https://cloud.appwrite.io/v1/avatars/initials?name=Test&project=xxx",
      "email": "xxx",
      "password": "xxx",
      "username": "Test"
    },
    {
      "$collectionId": "xxx",
      "$createdAt": "2024-04-22T16:42:10.526+00:00",
      "$databaseId": "xxx",
      "$id": "xxx",
      "$permissions": [Array],
      "$updatedAt": "2024-04-22T16:45:42.462+00:00",
      "accountId": "xxx",
      "avatar": "https://cloud.appwrite.io/v1/avatars/initials?name=Test2&project=xxx",
      "email": "xxx",
      "password": "xxx",
      "username": "Test2"
    }
  ],
  "prompt": "Abcprompt",
  "thumbnail": "https://cloud.appwrite.io/v1/storage/buckets/6623dbe60f9b23bfe619/files/66268a4511a67cbf7772/preview?width=2000&height=2000&gravity=top&quality=100&project=xxx",
  "title": "Abc",
  "video": "https://cloud.appwrite.io/v1/storage/buckets/6623dbe60f9b23bfe619/files/66268a45619cf6629001/view?project=xxx"
}

To retrieve posts liked by a user, I’m using the following query:

// Get video posts Liked by user
export async function getUserLikedPosts(userId) {
  try {
    const posts = await databases.listDocuments(
      appwriteConfig.databaseId,
      appwriteConfig.videoCollectionId,
      [Query.equal("likebyusers", [userId])]
    );
    return posts.documents;
  } catch (error) {
    console.log(error);
    throw new Error(error);
  }
}

However, I encountered the following error in the console: AppwriteException: Invalid query: Cannot query on virtual relation attribute.

Could someone help me understand and resolve this issue? Any insights would be greatly appreciated.


Collection Structure: My Project’s Data Model

I’ve meticulously designed a collection structure for my project and would greatly appreciate feedback to ensure it aligns with best practices and efficiency standards. Below, I present the structure I’ve crafted:

Users Collection:

KEY TYPE DEFAULT VALUE
username String
email Email
password String
avatar Url
accountId String
videos Relationship with videos

Explanation:

  • Username: Represents the unique username of each user.
  • Email: Stores the email address associated with each user.
  • Password: Stores the encrypted password for user authentication.
  • Avatar: Stores the URL of the user’s profile picture.
  • AccountId: Unique identifier for each user’s account.
  • Videos: Establishes a relationship with the videos uploaded by each user.

Videos Collection:

KEY TYPE DEFAULT VALUE
title String
prompt String
video Url
thumbnail Url
creator Relationship with creator
likebyusers Relationship with likebyusers

Explanation:

  • Title: Represents the title of each video.
  • Prompt: Provides additional information or context for the video.
  • Video: Stores the URL of the video content.
  • Thumbnail: Stores the URL of the video’s thumbnail image.
  • Creator: Establishes a relationship with the user who created the video.
  • Likebyusers: Establishes a relationship with users who have liked the video.

Software Versions in Use

I’m currently employing the following versions in my project:

react-native-appwrite: ^0.2.2
devDependencies:
@babel/core: ^7.24.3
tailwindcss: 3.3.2
expo: ~50.0.14

I’m eagerly looking forward to any insights, suggestions, or critiques regarding this structure. Thank you in advance for your valuable input!


2

Answers


  1. Just out of curiosity, are you following a video tutorial while building this? Or is this your own thing? It could help me understand where the problem is if it’s also part of a tututorial.

    Here’s where I think your issue is:

    When saving users in the likebyusers array you are saving the user object, which I wouldn’t recommend. Instead try just saving the user ID.

        const existingLikeByUsers = postDocument.likebyusers;
        const result = await getCurrentUser();
        //const updatedLikeByUsers = [...existingLikeByUsers, result];
        const updatedLikeByUsers = [...existingLikeByUsers, result.$id];
    

    From here, you are trying to find all the posts liked by a specific user, however, you are using a string ID to compare against an entire object, that wont work.

        const posts = await databases.listDocuments(
          appwriteConfig.databaseId,
          appwriteConfig.videoCollectionId,
          [Query.equal("likebyusers", [userId])]
        );
    

    Here is what I would recommend.

    First, save only the user id in the array:

    const result = await getCurrentUser();
    const updatedLikeByUsers = [...existingLikeByUsers, result.$id];
    

    Then, when performing your query, you can do this with the new contains operator. The equal operator should still work here as well so you can try both:

    const posts = await databases.listDocuments(
          appwriteConfig.databaseId,
          appwriteConfig.videoCollectionId,
          [Query.contains("likebyusers", [userId])]
        );
    
    Login or Signup to reply.
  2. Guess it is an extra task from one video guide, where it says to create a relation, but AppWrite has some limits to virtual attributes search.

    Instead i presume to create an Array of strings, as it was mentioned before by Dennis Ivy

    then you just could do a simple query request like this

        const likedPosts = await databases.listDocuments(
        appwriteConfig.databaseId,
        appwriteConfig.videoCollectionId,
        [Query.contains('liked_flag', userId)]
    );
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search