Search User Based on Latlong With Distance Golang Mongodb
Location based search in golang with mongodb#
If you are building api for any of the location based app then there must be scenario where you have to search users within certain radius using users current location.
so that can be done very easily with mongodb because mongodb have built in 2dsphere
index which will handle the calculation part of latitude and longitude.
Suppose you have collection of users with structure like below
{
"_id":"62efa58350aa6f9bd41f3eff",
"first_name":"john",
"last_name":"Doe",
"email":"abc@exaple.com"
}
Now add one more property location
which will store latitude and longitude of the users
location
should have two sub proprty one is type
and second is coordinates
.
type
will be Point
and coordinates
will be array [longitude, latitude].
make sure that first value in coordinates
is longitude
.
user collection will look like this.
{
"_id":"62efa58350aa6f9bd41f3eff",
"first_name":"john",
"last_name":"Doe",
"email":"abc@exaple.com",
"location": {
"type": "Point",
"coordinates": [-122.4545454,37.4354545],
}
}
now add index on location field which will be of type 2dsphere
.
Now i will create a Search function for searching users. this will be like below.
there should be only one child property in m mongo.Pipeline
so if you want additional filters along with lat long you can add that into $geoNear
> query
property like service_category
.#
search.go
package main
import (
"context"
"fmt"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
)
const (
UsersCollection = "users"
)
type Location struct {
Type string `json:"type" bson:"type"`
Coordinates []float64 `json:"coordinates" bson:"coordinates"`
}
type User struct {
ID string `json:"id" bson:"_id"`
Firstname string `json:"first_name" bson:"first_name"`
Lastname string `json:"last_name" bson:"last_name"`
Email string `json:"email" bson:"email"`
Location Location `json:"location" bson:"location"`
}
func Search(latitude, longitude float64) ([]*User, error) {
location := Location{
"Point",
[]float64{longitude, latitude},
}
filter :=
bson.D{
{"$geoNear",
bson.D{
{"near", location},
{"maxDistance", 5000},
{"spherical", true},
{"distanceField", "distance"},
{"distanceMultiplier", 1}, // this means distance field will be in meter
{"query", bson.D{
{"service_category", categoryId}, // Additional Filters
}},
},
},
}
client := mongodb.NewMongo()
defer client.CloseMongo()
db := client.GetMongoDB()
var result []*User
cursor, err := db.Collection(UsersCollection).Aggregate(context.TODO(), mongo.Pipeline{filter})
if err != nil {
fmt.Println(err.Error())
return nil, err
}
if err = cursor.All(context.TODO(), &result); err != nil {
fmt.Println(err)
return nil, err
}
defer cursor.Close(context.TODO())
return result, nil
}
Connecting mongodb with golang#
for connectivity with mongodb database create a mongodb
folder in root of the project and create mongo.go
file with the following content
mongodb/mongo.go
package mongodb
import (
"context"
"fmt"
"os"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"github.com/joho/godotenv"
)
func init() {
err := godotenv.Load("../.env")
if err != nil {
log.Println(err.Error())
}
}
type Mongodb struct {
client *mongo.Client
}
var MongoClient *Mongodb
func NewMongo() *Mongodb {
// uri := os.Getenv("MONGODB_URI")
dbName := os.Getenv("DB_NAME")
dbHost := os.Getenv("DB_HOST")
dbUsername := os.Getenv("DB_USERNAME")
dbPassword := os.Getenv("DB_PASSWORD")
connectionString := fmt.Sprintf("mongodb+srv://%s:%s@%s/%s?retryWrites=true&w=majority", dbUsername, dbPassword, dbHost, dbName)
fmt.Println(connectionString)
client, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(connectionString))
if err != nil {
panic(err)
}
MongoClient = &Mongodb{
client: client,
}
return MongoClient
}
func (m *Mongodb) GetMongoDB() *mongo.Database {
dbName := os.Getenv("DB_NAME")
return m.client.Database(dbName)
}
func (m *Mongodb) CloseMongo() {
if err := m.client.Disconnect(context.TODO()); err != nil {
panic(err)
}
}
Do not forget to create .env
file in root folder with all the database connection details.
Now its time to use your Search()
function in main file.
This is how your main.go
file will look like
main.go
package main
import (
"fmt"
"encoding/json"
)
func main() {
latitude := 36.34343436
longitude := -122.3234266654
users, err := Search(latitude, longitude)
if err != nil {
fmt.Println(err)
return
}
jsonString, err := json.Marshal(users)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(jsonString))
}
I hope this is enough for you to get started working with mongodb and latlong search in golang, for any doubt you can comment or send me a mail so that i can help.
mailid - dheerajv4855@gmail.com