Our latest release Appwrite 1.3 includes the most requested feature, Database Relationships 🎉 While relationships deserve all the spotlight, we are bringing many more exciting features. Databases were the focus of this release and got some new and shiny query operators, such as Query.select()
or Query.isNull()
. Databases now allow give you more freedom with some of the index and page limits eliminated. Oh, and I can’t stress this enough, the new Console UI with configurable layout options and a multi-level menu is just beautiful 😍 Auth service got some thrilling new password policy configurations and Teams API now lets you set team preferences. Functions service got improvements to variables UI in Appwrite Console, and that’s not even everything! Grab your favorite snack and enjoy our announcement. 🍿
🤔 New to Appwrite?
Appwrite is an open-source back-end-as-a-service that abstracts all the complexity of building a modern application by providing you with a set of REST, GraphQL, and Realtime APIs for your core back-end needs. Appwrite takes the heavy lifting for developers and handles user authentication and authorization, databases, file storage, cloud functions, webhooks, and much more!
🔗 Relationships in Database Service
Appwrite Databases lets you store your data and share it with all of your app users. Relationships allow you to create connections between your data to make them predictable, consistent, and easy to work with. With Relationships Beta added to Appwrite, you can now set up the four most common types of relationships directly in your Appwrite Console, and start querying your data together.
With one-to-one and many-to-one relations, you can now store similar data in separate collections to have separate permission rules. This lets you build secure apps but still keep reading data exceptionally simple.
One-to-many relations bring a powerful replacement to all of your array attributes. With a related collection, you can now store data of any complexity, and query it as you like. You can also get all the data in one request without any need to do mapping on the client side.
Many-to-many relationships are now much simpler. You no longer need to manage your own junction table as we do it for you.
As complex as relationships sound, with Appwrite, there is no need to write lengthy queries. After setting up a relationship, simply read your documents and get exactly what you expect:
const databases = new Databases(client);
const response = await databases.listDocuments('production', 'calendars');
console.log(response);
{
"total": 1,
"documents": [
{
"title": "Meetings",
"events": [
{ "name": "Lunch Break", "date": "2023-04-03T16:30:00.000+00:00" },
{ "name": "Onboarding", "date": "2023-04-03T18:00:00.000+00:00" }
]
}
]
}
It’s that easy! 🤩 If the response payload ever grows too big, with the new Query.select()
operator you can ask for only attributes you are interested in. More on that in a later section 🤫
🤸 Databases Getting Flexier
Maximum page size and indexes make end-product faster but can create a lot of road bumps during development. These limits even created a blocker for some use cases. Not anymore!
The maximum page size for getting your documents was capped at 100. In Appwrite 1.3, this limit was eliminated. We noticed it felt limiting to many projects and implementing infinite cursor pagination wasn’t a cup of tea for everyone. While it is not recommended to query millions of documents in a single request, we made sure to provide you with tools, and yet you, a developer, make the decision.
Strict indexes for queries in Appwrite 1.3 are no longer necessary! If you ever used Appwrite Databases, chances are, you have seen the error ⚠️Index Not Found
. Such strict indexes can get in the way during development and can be a blocker to some use cases with complex filtering possibilities. With Appwrite 1.3, you are no longer going to get errors telling you to set up an index.
Let’s get a little crazy and see what we can do now:
const databases = new Databases(client);
const response = await databases.listDocuments('production', 'events', [
Query.limit(999999),
Query.orderDesc('$id'),
Query.orderAsc('name'),
Query.orderDesc('date'),
Query.greaterThan('duration', 60 * 60),
Query.search('description', 'urgent')
]);
console.log(response);
As complex as this looks, Appwrite will accept this query and give you the results. As your app grows and this query gets slower, make sure to add indexes!😅
🔍 New Database Queries
Since we released the last database refactor in Appwrite 1.0, we noticed a huge increase in developers using Appwrite Databases. Databases became much quicker, more powerful, and more stable. With all the new feedback from our community, we noticed queries need some more attention, which is exactly what we did 😎
We are proud to announce the most requested query Query.isNull()
alongside Query.isNotNull()
. Null query lets you check if the value of an attribute in the document was provided, or was left empty during the creation of the document.
With relationships added to databases, we decided to also introduce Query.select()
to allow developers to specify what attributes they are interested in, similarly to how it can be done with GraphQL. Specifying attributes with a select query not only decreases the size of the response, but also makes underlying queries faster and more efficient.
We also added Query.startsWith()
and Query.endsWith()
to bring some more searching possibilities to your string attributes. While this doesn’t sound like much, it is a great addition for many applications as workarounds for this feature were overcomplicated.
Last but not least, we added a Query.between()
to improve the performance of your numeric and datetime queries when you are looking for a specific range. This was already possible with Query.greaterThan()
and Query.lessThan()
, but by using Query.between()
we have seen improvements in performance. We are constantly working on adding new query capabilities and plan to keep introducing new ones in the future with each release.
Let’s bring all the queries together and see them in action!
const databases = new Databases(client);
const response = await databases.listDocuments('production', 'profiles', [
Query.isNotNull('employerId'),
Query.startsWith('phoneNumber', '+61'),
Query.between('age', 15, 18),
Query.select(['twitterUrl', 'linkedInUrl'])
]);
console.log(response);
We just filtered profiles to only see unemployed folks with a phone number from Canada, and a good age for student part-time job. We are only fetching their socials, so we can easily get in touch with them.
✨ Improved Passwords Security
To keep users of your application safe, Appwrite already had a minimum of 8 character limit for the password. Today we have improved password security with two new rules. 🔥
With Appwrite 1.3 you can now enable password history and configure its length. With password history enabled, your users won’t be allowed to use the exact same password that they used previously when changing their password. The length of password history lets you set how much into the past should Appwrite remember, a maximum of up to 20 passwords.
You can now also enable a rule for password dictionary. Appwrite knows what are the most common passwords, and with this rule enabled, it will not allow you users to set any of those passwords. It prevents your users from having passwords like password
, 123456678
, or qwertyui
. Appwrite currently knows the 10,000 most commonly used passwords thanks to the same list used by other industry-leading auth providers. You can check out the dictionary list on GitHub.
🧑🤝🧑 Teams Get Preferences
Teams API got an upgrade and can now store preferences on teams. Similarly to user preferences, this feature is intended to help you store app configuration and apply it in a proper scope. You can, for example, use team preferences for business apps where the team owner (IT department in a company) does all the configuration and layout setup. Then all team members (all employees) read this setup from preferences and see the app in exactly the same way.
With this addition to the preferences family, you can now store preferences on all necessary levels. Let’s consider a scenario when we are storing if a dark theme is enabled or not. By writing to a local device, you are creating a preference on the session level. When you open the app on a new device, you will no longer have the dark theme. By using user preferences and storing them on the user level, the dark theme would be enabled as soon as you sign into your account. Finally, with team-level preferences, you can share the theme with multiple users such as students, employees, friends, or the community.
🔑 Importing Function Variables
Variables in Appwrite Functions lets you set secrets that you can securely access in your code. With Appwrite 1.3 we added a highly-requested button to Import .env file
🤯 With this new feature you can drag&drop the .env
file from your function folder and Console will take care of adding all variables defined in there. Additionally, all existing variables get updated with values from your file. This is exciting for those of us who have many variables and don’t want to create them one by one.
⏩ What’s Next?
With Appwrite 1.3 out in the public, we are starting to actively work on features for Appwrite 1.4. Some of you may have already noticed GitHub activity around Functions, which we plan to be our focus for the next release. As always, we are looking forward to hearing feedback from you and prioritizing features YOU are anticipating.
📚 Learn More
You can use the following resources to learn more and get help:
Top comments (9)
What an amazing looking release, can't wait to try relational databases directly in Appwrite
(and the .env variable import for function is a long time awaited one for me !)
Yeah, slowly but surely, Appwrite is fulfilling all your wishes.
Relationships is in Beta, so we really would appreciate your feedback!
how do we access the documentation on relationships? I cannot seem to find it
Hehe we need a search bar in docs. Another good opportunity to push for this effort.
appwrite.io/docs/databases-relatio...
This is great, i really liked the fact that it takes care of the update anomaly problem.
I have one suggestion, can we also add a feature to allow one level of nesting data?
For example if i have to store an image data, i have to create 3fields in the same document right now, width,height and file of image.
What if we can store it inside a single json type field
{
image:{
width:number,
height:number,
file:string
}
}
this is great!
Nice!
Great work guys. Gonna upgrade mine to this release ^^
Great!