/p/g17khqpukees4237dtn3astzapmp462vjhsz6st4/datastore
Datastore Package
Package provides support to store multiple collections of records.
It supports the definition of multiple storages, where each one is a collection of records. Records can have any number of user defined fields which are added dynamically when values are set on a record. These fields can also be renamed or removed.
Storages have support for simple schemas that allow users to pre-define fields which can optionally have a default value also defined. Default values are assigned to new records on creation.
User defined schemas can optionally be strict, which means that records from a storage using the schema can only assign values to the pre-defined set of fields. In which case, assigning a value to an unknown field results in an error.
Package also supports the definition of custom record indexes. Indexes are used by storages to search and iterate records. The default index is the ID index but custom single and multi value indexes can be defined.
Warning
Using this package to store your realm data must be carefully considered. The fact that record fields are not strictly typed and can be renamed or removed could lead to issues if not careful when coding your realm(s). So it's recommended that you consider other alternatives first, like alternative patterns or solutions provided by the blockchain to deal with data, types and data migration for example.
Repository can be found at jeronimoalbi/gnome,
as part of jeronimoalbi's Gno smart contracts monorepo.
Usage
1package main
2
3import "gno.land/p/g17khqpukees4237dtn3astzapmp462vjhsz6st4/datastore"
4
5func main() {
6 db := datastore.NewDatastore()
7
8 // Define a unique case insensitive index for user emails
9 emailIdx := datastore.NewIndex("email", func(r datastore.Record) string {
10 return r.MustGet("email").(string)
11 }).Unique().CaseInsensitive()
12
13 // Create a new storage for user records
14 users := db.CreateStorage("users", datastore.WithIndex(emailIdx))
15
16 // Add a user with a single "email" field
17 user := users.NewRecord()
18 user.Set("email", "[email protected]")
19
20 // Save to assign the user ID and update indexes
21 user.Save()
22
23 // Find user by email using the custom index
24 user, _ = users.Get(emailIdx.Name(), "[email protected]")
25 println("Found by email:", user.MustGet("email"))
26
27 // Find user by ID
28 user, _ = users.GetByID(user.ID())
29 println("Found by ID:", user.ID())
30
31 // Delete the user from the storage and update indexes
32 users.Delete(user.ID())
33 println("Users:", users.Size())
34}
35
36// Output:
37// Found by email: [email protected]
38// Found by ID: 1
39// Users: 0
Querying
1package main
2
3import "gno.land/p/g17khqpukees4237dtn3astzapmp462vjhsz6st4/datastore"
4
5func main() {
6 db := datastore.NewDatastore()
7
8 // Define a multi value index to search posts by tag
9 tagsIdx := datastore.NewMultiValueIndex("tags", func(r datastore.Record) []string {
10 return r.MustGet("tags").([]string)
11 })
12
13 posts := db.CreateStorage("posts", datastore.WithIndex(tagsIdx))
14 for _, title := range []string{"Post 1", "Post 2", "Post 3"} {
15 post := posts.NewRecord()
16 post.Set("title", title)
17 post.Set("tags", []string{"gno", title})
18 post.Save()
19 }
20
21 // Get two records starting from the second one
22 recordset, err := posts.Query(datastore.WithOffset(1), datastore.WithSize(2))
23 if err != nil {
24 panic(err)
25 }
26
27 recordset.Iterate(func(r datastore.Record) bool {
28 println("Post:", r.MustGet("title"))
29 return false // Continue iterating
30 })
31
32 // Get all the records that have the "gno" tag using the custom index
33 recordset = posts.MustQuery(datastore.UseIndex("tags", "gno"))
34 println("Tagged posts:", recordset.Size())
35}
36
37// Output:
38// Post: Post 2
39// Post: Post 3
40// Tagged posts: 3