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 | – |
– | ||
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
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.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.
Here is what I would recommend.
First, save only the user id in the array:
Then, when performing your query, you can do this with the new
contains
operator. Theequal
operator should still work here as well so you can try both: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