Created
September 8, 2017 10:55
-
-
Save aliuygur/2bd0e815aa898cb501f3d67a7c53b91e to your computer and use it in GitHub Desktop.
mongo golang examples
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package mongo | |
import ( | |
mgo "gopkg.in/mgo.v2" | |
"gopkg.in/mgo.v2/bson" | |
) | |
type ( | |
nextID struct { | |
Next uint64 `bson:"n"` | |
} | |
) | |
const idTbl = `ids` | |
// id returns next id. | |
// if sess nil then it uses default session | |
func (r *repository) id(c string) uint64 { | |
ids := r.c(idTbl) | |
change := mgo.Change{ | |
Update: bson.M{"$inc": bson.M{"n": 1}}, | |
Upsert: true, | |
ReturnNew: true, | |
} | |
id := new(nextID) | |
ids.Find(bson.M{"_id": c}).Apply(change, id) | |
return id.Next | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package mongo | |
import ( | |
"github.com/alioygur/fb-tinder-app/domain" | |
"github.com/alioygur/fb-tinder-app/service" | |
"gopkg.in/mgo.v2" | |
"gopkg.in/mgo.v2/bson" | |
) | |
type ( | |
fakePicture interface { | |
PutPicture(*domain.Image) error | |
PicturesByUserID(uint64) ([]*domain.Image, error) | |
ProfilePicture(uint64) (*domain.Image, error) | |
PictureByID(uint64) (*domain.Image, error) | |
PictureExistsByUserIDAndIsProfile(uint64, bool) (bool, error) | |
UpdatePicture(*domain.Image) error | |
DeletePicture(uint64) error | |
} | |
repository struct { | |
fakePicture | |
sess *mgo.Session | |
} | |
) | |
const ( | |
usersTbl = `users` | |
reactionsTbl = `reactions` | |
creditsTbl = `credits` | |
friendshipsTbl = `friendships` | |
matchesTbl = `matches` | |
abusesTbl = `abuses` | |
imagesTbl = `images` | |
) | |
// New instances new repository | |
func New(sess *mgo.Session) service.Repository { | |
return &repository{sess: sess} | |
} | |
// c returns mgo collection. | |
// if sess nil then it uses default session | |
func (r *repository) c(c string) *mgo.Collection { | |
return r.sess.DB("").C(c) | |
} | |
func (r *repository) oneBy(c *mgo.Collection, q interface{}, result interface{}) error { | |
return c.Find(q).One(result) | |
} | |
func (r *repository) oneByID(c *mgo.Collection, id uint64, result interface{}) error { | |
return r.oneBy(c, bson.M{"id": id}, result) | |
} | |
func (r *repository) existsBy(c *mgo.Collection, q interface{}) (bool, error) { | |
n, err := c.Find(q).Limit(1).Count() | |
return n > 0, err | |
} | |
func wrapErr(err error) error { | |
return err | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package mongo | |
import ( | |
"time" | |
"strconv" | |
mgo "gopkg.in/mgo.v2" | |
) | |
func randDBName() string { | |
return "testdb_" + strconv.Itoa(time.Now().Nanosecond()) | |
} | |
func newTestRepo(dropDB bool) (*repository, func(), error) { | |
dbname := randDBName() | |
sess, err := mgo.Dial("localhost/" + dbname) | |
if err != nil { | |
return nil, nil, nil | |
} | |
deferFnc := func() { | |
if dropDB { | |
sess.DB("").DropDatabase() | |
} | |
sess.Close() | |
} | |
r := repository{sess: sess} | |
return &r, deferFnc, nil | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package mongo | |
import ( | |
"time" | |
"gopkg.in/mgo.v2/bson" | |
"github.com/alioygur/fb-tinder-app/domain" | |
"github.com/pkg/errors" | |
) | |
type ( | |
user struct { | |
domain.User `bson:",inline"` | |
FriendList []uint64 `bson:"friend_list"` | |
} | |
) | |
func (r *repository) AddUser(du *domain.User) error { | |
now := time.Now().Round(time.Second) | |
du.CreatedAt = now | |
du.UpdatedAt = now | |
du.ID = r.id(usersTbl) | |
var u user | |
u.User = *du | |
return r.c(usersTbl).Insert(&u) | |
} | |
func (r *repository) UserByID(id uint64) (*domain.User, error) { | |
var u domain.User | |
err := r.c(usersTbl).Find(bson.M{"id": id}).One(&u) | |
return &u, errors.WithStack(wrapErr(err)) | |
} | |
func (r *repository) UserByEmail(email string) (*domain.User, error) { | |
var u domain.User | |
err := r.c(usersTbl).Find(bson.M{"email": email}).One(&u) | |
return &u, errors.WithStack(wrapErr(err)) | |
} | |
func (r *repository) UserByFacebookID(id uint64) (*domain.User, error) { | |
var u domain.User | |
err := r.c(usersTbl).Find(bson.M{"facebook_id": id}).One(&u) | |
return &u, errors.WithStack(wrapErr(err)) | |
} | |
func (r *repository) ExistsByEmail(email string) (bool, error) { | |
n, err := r.c(usersTbl).Find(bson.M{"email": email}).Count() | |
return n > 0, errors.WithStack(err) | |
} | |
func (r *repository) UserExistsByID(id uint64) (bool, error) { | |
n, err := r.c(usersTbl).Find(bson.M{"id": id}).Count() | |
return n > 0, errors.WithStack(err) | |
} | |
func (r *repository) UserExistsByFacebookID(id uint64) (bool, error) { | |
n, err := r.c(usersTbl).Find(bson.M{"facebook_id": id}).Count() | |
return n > 0, errors.WithStack(err) | |
} | |
func (r *repository) UpdateUser(u *domain.User) error { | |
u.UpdatedAt = time.Now() | |
err := r.c(usersTbl).Update(bson.M{"id": u.ID}, u) | |
return errors.WithStack(wrapErr(err)) | |
} | |
func (r *repository) SyncUserFriendsByFacebookID(user uint64, friends []uint64) error { | |
return nil | |
} | |
func (r *repository) BindFriends(users ...*domain.User) error { | |
count := len(users) | |
errc := make(chan error, count) | |
for _, u := range users { | |
go func(u *domain.User) { | |
sess := r.sess.Copy() | |
defer sess.Close() | |
c := r.c(usersTbl).With(sess) | |
var res struct { | |
FriendList []uint64 `bson:"friend_list"` | |
} | |
if err := c.Find(bson.M{"id": u.ID}).Select(bson.M{"friend_list": 1}).One(&res); err != nil { | |
errc <- errors.WithStack(err) | |
return | |
} | |
err := c.Find(bson.M{"id": bson.M{"$in": res.FriendList}}).All(&u.Friends) | |
errc <- errors.WithStack(err) | |
}(u) | |
} | |
// check for errors | |
for i := 0; i < count; i++ { | |
if err := <-errc; err != nil { | |
return err | |
} | |
} | |
return nil | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package mongo | |
import ( | |
"testing" | |
"gopkg.in/mgo.v2/bson" | |
"reflect" | |
"github.com/alioygur/fb-tinder-app/domain" | |
) | |
func Test_repository_PutUser(t *testing.T) { | |
r, deferFnc, err := newTestRepo(true) | |
if err != nil { | |
t.Fatal(err) | |
} | |
defer deferFnc() | |
want := domain.NewUser() | |
want.FirstName = "Ali" | |
want.LastName = "OYGUR" | |
want.Email = "[email protected]" | |
if err := r.AddUser(want); err != nil { | |
t.Error(err) | |
return | |
} | |
var got domain.User | |
if err := r.c(usersTbl).Find(bson.M{"id": want.ID}).One(&got); err != nil { | |
t.Error(err) | |
return | |
} | |
got.Friends = make([]*domain.User, 0) | |
if !reflect.DeepEqual(got, *want) { | |
t.Errorf("not equal, got %+v, want %+v", got, want) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment