Skip to content

Instantly share code, notes, and snippets.

@CaryBourgeois
Created May 8, 2019 13:58
Show Gist options
  • Save CaryBourgeois/9290e1edb5166d673814c7514a0b82df to your computer and use it in GitHub Desktop.
Save CaryBourgeois/9290e1edb5166d673814c7514a0b82df to your computer and use it in GitHub Desktop.
Simple Users Groups Graph Example
/*
* Copyright 2018 Fauna, Inc.
*
* Licensed under the Mozilla Public License, Version 2.0 (the "License"); you may
* not use this software except in compliance with the License. You may obtain a
* copy of the License at
*
* http://mozilla.org/MPL/2.0/
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package main
import (
f "github.com/fauna/faunadb-go/faunadb"
"log"
"math/rand"
)
var (
adminSecret = "secret"
endpoint = f.Endpoint("http://127.0.0.1:8443")
schema = Schema{
Database: f.Obj{
"name": "UserGroupEdge",
},
Classes: []f.Obj{
{ "name": "users"},
{ "name": "groups"},
{ "name": "edges"},
},
Indexes: []f.Obj{
{ "name": "users_all",
"source": f.Class("users")},
{ "name": "groups_all",
"source": f.Class("groups")},
{ "name": "edges_all",
"source": f.Class("edges")},
{ "name": "edges_user_groups",
"source": f.Class("edges"),
"terms": f.Arr{f.Obj{"field": f.Arr{"data", "user_id"}}}},
{ "name": "edges_group_users",
"source": f.Class("edges"),
"unique": true,
"terms": f.Arr{f.Obj{"field": f.Arr{"data", "group_id"}}},
"values": f.Arr{f.Obj{"field": f.Arr{"data", "user_id"}}}},
{ "name": "edges_group_users_role",
"source": f.Class("edges"),
"unique": true,
"terms": f.Arr{f.Obj{"field": f.Arr{"data", "group_id"}}},
"values": f.Arr{f.Obj{"field": f.Arr{"data", "user_role"}}, f.Obj{"field": f.Arr{"data", "user_id"}}}},
},
}
schemaConfig = SchemaConfig{
SkipSchema: true,
SkipDatabase: false,
SkipClass: false,
SkipIndex: false,
SkipData: false,
KeyPriority: 500,
}
)
type User struct {
ID int `fauna:"id"`
}
type Group struct {
ID int `fauna:"id"`
}
type Edge struct {
User_ID int `fauna:"user_id"`
Group_ID int `fauna:"group_id"`
User_Role string `fauna:"user_role"`
}
func main() {
adminClient := f.NewFaunaClient(adminSecret, endpoint)
SetupSchema(&schema, adminClient, schemaConfig)
log.Printf("scopedKey: %s", schema.scopedKey)
dbClient := adminClient.NewSessionClient(schema.scopedKey)
groups := []int{1, 2}
//readUniqueUsersInMultipleGroups(dbClient, groups)
readCommonUsersInMultipleGroups(dbClient, groups)
readUniqueUsersInMultipleGroupsAndRole(dbClient, groups, "Role B")
readUniqueUsersInMultipleGroupsAndNotRole(dbClient, groups, "Role B")
}
func readUniqueUsersInMultipleGroups(client *f.FaunaClient, groups []int) {
var users []int
res, err := client.Query(
f.Paginate(
f.Union(
f.Map(
groups,
f.Lambda("x", f.MatchTerm(f.Index("edges_group_users"), f.Var("x"))))),
f.Size(100)))
if err != nil {
panic(err)
}
log.Println(res)
if err := res.At(f.ObjKey("data")).Get(&users); err != nil {
panic(err)
}
for i, user := range users {
log.Printf("%d, %d", i, user)
}
}
func readCommonUsersInMultipleGroups(client *f.FaunaClient, groups []int) {
var users []int
res, err := client.Query(
f.Map(
f.Paginate(
f.Intersection(
f.Map(
groups,
f.Lambda("x", f.MatchTerm(f.Index("edges_group_users_role"), f.Var("x"))))),
f.Size(100)),
f.Lambda(f.Arr{"user_role", "user_id"}, f.Var("user_id"))))
if err != nil {
panic(err)
}
log.Println(res)
if err := res.At(f.ObjKey("data")).Get(&users); err != nil {
panic(err)
}
for i, user := range users {
log.Printf("%d, %d", i, user)
}
}
func readUniqueUsersInMultipleGroupsAndRole(client *f.FaunaClient, groups []int, role string) {
var users []int
res, err := client.Query(
f.Map(
f.Filter(
f.Paginate(
f.Union(
f.Map(
groups,
f.Lambda("group_id", f.MatchTerm(f.Index("edges_group_users_role"), f.Var("group_id"))))),
f.Size(100)),
f.Lambda(f.Arr{"user_role", "user_id"}, f.Equals(f.Var("user_role"), role))),
f.Lambda(f.Arr{"user_role", "user_id"}, f.Var("user_id"))))
if err != nil {
panic(err)
}
log.Println(res)
if err := res.At(f.ObjKey("data")).Get(&users); err != nil {
panic(err)
}
for i, user := range users {
log.Printf("%d, %d", i, user)
}
}
func readUniqueUsersInMultipleGroupsAndNotRole(client *f.FaunaClient, groups []int, role string) {
var users []int
res, err := client.Query(
f.Map(
f.Filter(
f.Paginate(
f.Union(
f.Map(
groups,
f.Lambda("group_id", f.MatchTerm(f.Index("edges_group_users_role"), f.Var("group_id"))))),
f.Size(100)),
f.Lambda(f.Arr{"user_role", "user_id"}, f.Not(f.Equals(f.Var("user_role"), role)))),
f.Lambda(f.Arr{"user_role", "user_id"}, f.Var("user_id"))))
if err != nil {
panic(err)
}
log.Println(res)
if err := res.At(f.ObjKey("data")).Get(&users); err != nil {
panic(err)
}
for i, user := range users {
log.Printf("%d, %d", i, user)
}
}
/*
* This gets called from SetupSchema in the schema.go file for it must be implemented.
*/
func initData(client *f.FaunaClient) {
numUsers := 100
numGroups := 10
numEdges := 10 * 100
createUsers(client, numUsers)
createGroups(client, numGroups)
createEdges(client, numEdges, numUsers, numGroups)
}
func createEdges(client *f.FaunaClient, numEdges int, numUsers int, numGroups int) {
/*
* Create the goups by randomly assigning users to groups
*/
edges := make([]Edge, numEdges)
for _, edge := range edges {
edge.User_ID = rand.Intn(numUsers) + 1
edge.Group_ID = rand.Intn(numGroups) + 1
if edge.User_ID % 2 == 0 {
edge.User_Role = "Role B"
} else {
edge.User_Role = "Role A"
}
client.Query(
f.Create(f.Class("edges"), f.Obj{"data": edge}))
}
}
func createGroups(client *f.FaunaClient, numGroups int) {
/*
* Create the groups
*/
groups := make([]Group, numGroups)
for i, group := range groups {
group.ID = i + 1
}
res, err := client.Query(
f.Map(
groups,
f.Lambda("group",
f.Create(f.Class("groups"), f.Obj{"data": f.Var("group")}))))
if err != nil {
panic(err)
}
log.Printf("Created %d 'groups' \n%s", numGroups, res)
}
func createUsers(client *f.FaunaClient, numUsers int) {
/*
* Create the users
*/
users := make([]User, numUsers)
for i, user := range users {
user.ID = i + 1
}
res, err := client.Query(
f.Map(
users,
f.Lambda("user",
f.Create(f.Class("users"), f.Obj{"data": f.Var("user")}))))
if err != nil {
panic(err)
}
log.Printf("Created %d 'users' \n%s", numUsers, res)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment