package storage import ( "github.com/paulmach/orb" "github.com/paulmach/orb/geojson" "go.mongodb.org/mongo-driver/mongo" "github.com/spf13/viper" "go.mongodb.org/mongo-driver/mongo/options" "solidarity-service/utils" "context" "github.com/google/uuid" "encoding/json" "errors" "fmt" _ "github.com/lib/pq" "github.com/rs/zerolog/log" "strings" "sync" "time" "go.mongodb.org/mongo-driver/bson" "solidarity-service/internal" ) type MongoDBStorage struct { *mongo.Client DbName string Collections map[string]string } func NewMongoDBStorage(cfg *viper.Viper) (MongoDBStorage, error) { var ( mongodb_host = cfg.GetString("storage.db.mongodb.host") mongodb_port = cfg.GetString("storage.db.mongodb.port") mongodb_dbname = cfg.GetString("storage.db.mongodb.db_name") mongodb_groups = cfg.GetString("storage.db.mongodb.collections.groups") ////////////////////////code mongodb_groups_members = cfg.GetString("storage.db.mongodb.collections.groups_member") ) client, err := mongo.NewClient(options.Client().ApplyURI("mongodb://" + mongodb_host + ":" + mongodb_port)) if err != nil { return MongoDBStorage{}, err } err = client.Connect(context.TODO()) if err != nil { return MongoDBStorage{}, err } storage := MongoDBStorage{ Client: client, DbName: mongodb_dbname, Collections: map[string]string{ "groups": mongodb_groups, /////////////////////////////code "groups_member": mongodb_groups_members, }, } //TODO Indexes return storage, err } func (s MongoDBStorage) CreatePassenger(passenger internal.Passenger) (err error) { collection := s.Client.Database(s.DbName).Collection(s.Collections["users"]) _, err = uuid.Parse(passenger.Passenger.ID) if err != nil { log.Error().Err(err).Msg("MongoDB Storage CreatePassenger invalid ID") return err } if passenger.Passenger.Alias == "" || passenger.Passenger.Operator == "" { errMsg := "MongoDB Storage CreatePassenger empty alias or operator FQDN." log.Error().Msg(errMsg) return errors.New(errMsg) } // preferencesJSON, err := json.Marshal(passenger.Preferences) if err != nil { errMsg := "MongoDB Storage CreatePassenger Error encoding Preferences to JSON" log.Error().Err(err).Msg(errMsg) return errors.New(errMsg + err.Error()) } if _, err := collection.InsertOne(context.TODO(), passenger); err != nil { return err } // if err != nil { // if strings.Contains(err.Error(), utils.SQL_DUPLICATE) { // err = s.UpdatePassenger(passenger) // if err != nil { // return err // } // return nil // } // errMsg := "Postgresql Storage CreatePassenger Error inserting data into the database" // log.Error().Err(err).Msg(errMsg) // return errors.New(errMsg + err.Error()) // } return nil } func (s MongoDBStorage) UpdatePassenger(passenger internal.Passenger) (err error) { collection := s.Client.Database(s.DbName).Collection(s.Collections["users"]) _, err = uuid.Parse(passenger.Passenger.ID) if err != nil { log.Error().Err(err).Msg("MongoDB Storage UpdatePassenger invalid ID") return err } if passenger.Passenger.Alias == "" || passenger.Passenger.Operator == "" { errMsg := "MongoDB Storage UpdatePassenger empty alias or operator FQDN." log.Error().Msg(errMsg) return errors.New(errMsg) } // preferencesJSON, err := json.Marshal(passenger.Preferences) if err != nil { errMsg := "MongoDB Storage UpdatePassenger Error encoding Preferences to JSON" log.Error().Err(err).Msg(errMsg) return errors.New(errMsg + err.Error()) } if _, err := collection.ReplaceOne(context.TODO(), bson.M{"_id": passenger.Passenger.ID}, passenger); err != nil { fmt.Println(err) return err } if err != nil { errMsg := "MongoDB Storage UpdatePassenger Error updating data in the database" log.Error().Err(err).Msg(errMsg) return errors.New(errMsg + err.Error()) } return nil } func (s MongoDBStorage) GetPassenger(passengerID string) (passenger internal.Passenger, err error) { collection := s.Client.Database(s.DbName).Collection(s.Collections["users"]) var preferencesJSON []byte _ , err = uuid.Parse(passenger.Passenger.ID) if len(passengerID) == 0 { return passenger, errors.New("no group id provided") } else { _, err = collection.Find(context.TODO(), bson.M{"_id": bson.M{"$in": passengerID}}) if err != nil { return passenger, err } } if err != nil { errMsg := "MongoDB Storage GetPassenger Error querying data from the database" log.Error().Err(err).Msg(errMsg) return passenger, errors.New(errMsg + err.Error()) } err = json.Unmarshal(preferencesJSON, &passenger.Preferences) if err != nil { errMsg := "MongoDB Storage GetPassenger Error decoding Preferences from JSON" log.Error().Err(err).Msg(errMsg) return passenger, errors.New(errMsg + err.Error()) } return passenger, nil } func (s MongoDBStorage) CreateDriver(driver internal.Driver) (err error) { collection := s.Client.Database(s.DbName).Collection(s.Collections["users"]) //var availabilities []byte _, err = uuid.Parse(driver.Driver.ID) if err != nil { log.Error().Err(err).Msg("MongoDB Storage CreateDriver invalid ID") return err } //departureJSON, err := json.Marshal(driver.Driver_departure_address) if err != nil { errMsg := "MongoDB Storage CreateDriver Error encoding departure Feature to JSON" log.Error().Err(err).Msg(errMsg) return errors.New(errMsg + err.Error()) } //preferencesJSON, err := json.Marshal(driver.Preferences) if err != nil { errMsg := "MongoDB Storage CreateDriver Error encoding Preferences to JSON" log.Error().Err(err).Msg(errMsg + err.Error()) return errors.New(errMsg) } //carJSON, err := json.Marshal(driver.Car) if err != nil { errMsg := "MongoDB Storage CreateDriver Error encoding Car to JSON" log.Error().Err(err).Msg(errMsg) return errors.New(errMsg + err.Error()) } if driver.Driver.Alias == "" || driver.Driver.Operator == "" { errMsg := "MongoDB Storage CreateDriver empty alias or operator FQDN." log.Error().Msg(errMsg) return errors.New(errMsg) } if driver.AvailabilitiesType != internal.Punctual && driver.AvailabilitiesType != internal.Regular { errMsg := "MongoDB Storage CreateDriver invalid Availabilities Type" log.Error().Msg(errMsg) return errors.New(errMsg) } if driver.Radius == 0 { errMsg := "MongoDB Storage CreateDriver Radius has to be defined" log.Error().Msg(errMsg) return errors.New(errMsg) } switch driver.AvailabilitiesType { case internal.Punctual: //availabilities, err = json.Marshal(driver.PunctualAvailabilities) if err != nil { errMsg := "MongoDB Storage CreateDriver error converting Punctual availabilities" log.Error().Msg(errMsg) return errors.New(errMsg + err.Error()) } case internal.Regular: //availabilities, err = json.Marshal(driver.RegularAvailabilities) if err != nil { errMsg := "MongoDB Storage CreateDriver error converting Regular availabilities" log.Error().Msg(errMsg) return errors.New(errMsg + err.Error()) } } if _, err := collection.InsertOne(context.TODO(), driver); err != nil { return err } // if err != nil { // if strings.Contains(err.Error(), utils.SQL_DUPLICATE) { // err = s.UpdateDriver(driver) // if err != nil { // return err // } // return nil // } // errMsg := "MongoDB Storage CreateDriver Error inserting data into the database" // log.Error().Err(err).Msg(errMsg) // return errors.New(errMsg + err.Error()) // } return nil } func (s MongoDBStorage) UpdateDriver(driver internal.Driver) (err error) { collection := s.Client.Database(s.DbName).Collection(s.Collections["groups"]) //var availabilities []byte _, err = uuid.Parse(driver.Driver.ID) if err != nil { log.Error().Err(err).Msg("MongoDB Storage UpdateDriver invalid ID") return err } //departureJSON, err := json.Marshal(driver.Driver_departure_address) if err != nil { errMsg := "MongoDB Storage UpdateDriver Error encoding departure Feature to JSON" log.Error().Err(err).Msg(errMsg) return errors.New(errMsg + err.Error()) } //preferencesJSON, err := json.Marshal(driver.Preferences) if err != nil { errMsg := "MongoDB Storage UpdateDriver Error encoding Preferences to JSON" log.Error().Err(err).Msg(errMsg + err.Error()) return errors.New(errMsg) } //carJSON, err := json.Marshal(driver.Car) if err != nil { errMsg := "MongoDB Storage UpdateDriver Error encoding Car to JSON" log.Error().Err(err).Msg(errMsg) return errors.New(errMsg + err.Error()) } if driver.Driver.Alias == "" || driver.Driver.Operator == "" { errMsg := "MongoDB Storage UpdateDriver empty alias or operator FQDN." log.Error().Msg(errMsg) return errors.New(errMsg) } if driver.AvailabilitiesType != internal.Punctual && driver.AvailabilitiesType != internal.Regular { errMsg := "MongoDB Storage UpdateDriver invalid Availabilities Type" log.Error().Msg(errMsg) return errors.New(errMsg) } if driver.Radius == 0 { errMsg := "MongoDB Storage UpdateDriver Radius has to be defined" log.Error().Msg(errMsg) return errors.New(errMsg) } // switch driver.AvailabilitiesType { // case internal.Punctual: // availabilities, err = json.Marshal(driver.PunctualAvailabilities) // if err != nil { // errMsg := "MongoDB Storage UpdateDriver error converting Punctual availabilities" // log.Error().Msg(errMsg) // return errors.New(errMsg + err.Error()) // } // case internal.Regular: // availabilities, err = json.Marshal(driver.RegularAvailabilities) // if err != nil { // errMsg := "MongoDB Storage UpdateDriver error converting Regular availabilities" // log.Error().Msg(errMsg) // return errors.New(errMsg + err.Error()) // } // } if _, err := collection.ReplaceOne(context.TODO(), bson.M{"_id": driver.Driver.ID}, driver); err != nil { fmt.Println(err) return err } if err != nil { errMsg := "MongoDB Storage UpdateDriver Error updating data in the database" log.Error().Err(err).Msg(errMsg) return errors.New(errMsg + err.Error()) } return nil } func (s MongoDBStorage) GetDriver(driverID string) ( *internal.Driver, error) { collection := s.Client.Database(s.DbName).Collection(s.Collections["users"]) // var preferencesJSON []byte // var departureAddress []byte // var availabilitiesJSON []byte // var carJSON []byte driver := &internal.Driver{} if err := collection.FindOne(context.TODO(), bson.M{"_id": driverID}).Decode(driver); err != nil { return nil, err } // if err != nil { // errMsg := "MongoDB Storage GetDriver Error querying data from the database" // log.Error().Err(err).Msg(errMsg) // return driver, errors.New(errMsg + err.Error()) // } // err = json.Unmarshal(preferencesJSON, &driver.Preferences) // if err != nil { // errMsg := "MongoDB Storage GetDriver Error decoding Preferences from JSON" // log.Error().Err(err).Msg(errMsg) // return driver, errors.New(errMsg + err.Error()) // } // err = json.Unmarshal(carJSON, &driver.Car) // if err != nil { // errMsg := "MongoDB Storage GetDriver Error decoding Car from JSON" // log.Error().Err(err).Msg(errMsg) // return driver, errors.New(errMsg + err.Error()) // } // driver.Driver_departure_address, err = geojson.UnmarshalFeature(departureAddress) // if err != nil { // errMsg := "MongoDB Storage GetDriver Error decoding Driver departure route into GeoJSON" // log.Error().Err(err).Msg(errMsg) // return driver, errors.New(errMsg + err.Error()) // } // switch driver.AvailabilitiesType { // case Regular: // err = json.Unmarshal(availabilitiesJSON, &driver.RegularAvailabilities) // if err != nil { // errMsg := "MongoDB Storage GetDriver Error decoding Regular Availabilities from JSON" // log.Error().Err(err).Msg(errMsg) // return driver, errors.New(errMsg + err.Error()) // } // case Punctual: // err = json.Unmarshal(availabilitiesJSON, &driver.PunctualAvailabilities) // if err != nil { // errMsg := "MongoDB Storage GetDriver Error decoding Punctual Availabilities from JSON" // log.Error().Err(err).Msg(errMsg) // return driver, errors.New(errMsg + err.Error()) // } // default: // errMsg := "MongoDB Storage GetDriver Invalid Availabilities Type" // log.Error().Msg(errMsg) // return driver, errors.New(errMsg + err.Error()) // } return driver, nil } func (s MongoDBStorage) CreateBooking(booking internal.BookingRequest) (err error) { collection := s.Client.Database(s.DbName).Collection(s.Collections["users"]) _, err = uuid.Parse(booking.Driver_id) if err != nil { log.Error().Err(err).Msg("MongoDB Storage CreateBooking invalid Driver ID") return err } _, err = uuid.Parse(booking.Passenger_id) if err != nil { log.Error().Err(err).Msg("MongoDB Storage CreateBooking invalid Passenger ID") return err } _, err = uuid.Parse(booking.ID) if err != nil { log.Error().Err(err).Msg("MongoDB Storage CreateBooking invalid Booking ID") return err } if booking.Operator == "" { log.Error().Err(err).Msg("MongoDB Storage CreateBooking empty operator") return err } //departureJSON, err := json.Marshal(booking.Departure_address) if err != nil { errMsg := "MongoDB Storage CreateBooking Error encoding departure Feature to JSON" log.Error().Err(err).Msg(errMsg) return errors.New(errMsg + err.Error()) } //destinationJSON, err := json.Marshal(booking.Destination_address) if err != nil { errMsg := "MongoDB Storage CreateBooking Error converting destination Feature to JSON" log.Error().Err(err).Msg(errMsg) return errors.New(errMsg + err.Error()) } if booking.Pickup_date == 0 { errMsg := "MongoDB Storage CreateBooking empty UNIX pickup Date timestamp" log.Error().Err(err).Msg(errMsg) return errors.New(errMsg) } booking.Distance = utils.Haversine(booking.Departure_address.Point().Lat(), booking.Departure_address.Point().Lon(), booking.Destination_address.Point().Lat(), booking.Destination_address.Point().Lon()) booking.Duration, _ = utils.CalculateDurationBetweenFeatures(booking.Departure_address, booking.Destination_address) if _, err := collection.InsertOne(context.TODO(), booking); err != nil { return err } if err != nil { errMsg := "MongoDB Storage CreateBooking Error inserting data into the database" log.Error().Err(err).Msg(errMsg) return errors.New(errMsg + err.Error()) } return nil } func (s MongoDBStorage) GetBooking(bookingID string) (*internal.Booking, error) { collection := s.Client.Database(s.DbName).Collection(s.Collections["users"]) //var departureAddress []byte //var destinationAddress []byte booking := &internal.Booking{} if err := collection.FindOne(context.TODO(), bson.M{"_id": bookingID}).Decode(booking); err != nil { return nil, err } // if err != nil { // errMsg := "MongoDB Storage GetBooking Error getting booking" // log.Error().Err(err).Msg(errMsg) // return internal.Booking{}, errors.New(errMsg + err.Error()) // } // booking.PassengerPickupAddress, err = geojson.UnmarshalFeature(departureAddress) // if err != nil { // errMsg := "MongoDB Storage GetBooking Error decoding Driver departure route into GeoJSON" // log.Error().Err(err).Msg(errMsg) // return internal.Booking{}, errors.New(errMsg + err.Error()) // } // booking.PassengerDropAddress, err = geojson.UnmarshalFeature(destinationAddress) // if err != nil { // errMsg := "MongoDB Storage GetBooking Error decoding Driver destination route into GeoJSON" // log.Error().Err(err).Msg(errMsg) // return internal.Booking{}, errors.New(errMsg + err.Error()) // } passenger, err := s.GetPassenger(booking.Passenger.ID) if err != nil { errMsg := "MongoDB Storage GetBooking Error getting passenger" log.Error().Err(err).Msg(errMsg) return booking, errors.New(errMsg + err.Error()) } booking.Passenger = passenger.Passenger driver, err := s.GetDriver(booking.Driver.ID) if err != nil { errMsg := "MongoDB Storage GetBooking Error getting driver" log.Error().Err(err).Msg(errMsg) return booking, errors.New(errMsg + err.Error()) } booking.Driver = driver.Driver return booking, nil } func (s MongoDBStorage) UpdateBookingStatus(bookingStatusID string, status internal.BookingStatus) (err error) { collection := s.Client.Database(s.DbName).Collection(s.Collections["users"]) _, err = uuid.Parse(bookingStatusID) if err != nil { log.Error().Err(err).Msg("MongoDB Storage UpdateBookingStatus invalid Booking ID") return err } _, err = s.GetBooking(bookingStatusID) if err != nil { return errors.New(err.Error()) } if _, err := collection.ReplaceOne(context.TODO(), bson.M{"_id": bookingStatusID}, status); err != nil { fmt.Println(err) return err } return nil } func (s MongoDBStorage) FilterUserBookingsByStatus(userType string, status internal.BookingStatus, userID string) (bookings []internal.Booking, err error) { collection := s.Client.Database(s.DbName).Collection(s.Collections["groups"]) if err != nil { return nil, errors.New("invalid UUID") } if userType != "driver" && userType != "passenger" { return nil, errors.New("invalid user type") } var cur *mongo.Cursor findOptions := options.Find() if len(userID) == 0 { return bookings, errors.New("no group id provided") } else { cur, err = collection.Find(context.TODO(), bson.M{"_id": bson.M{"$in": userID}}, findOptions) if err != nil { return bookings, err } } for cur.Next(context.TODO()) { var group internal.Booking var elem bson.M if err := cur.Decode(&elem); err != nil { return bookings, err } bsonBytes, _ := bson.Marshal(elem) bson.Unmarshal(bsonBytes, &group) bookings = append(bookings, group) } var wg sync.WaitGroup //var mu sync.Mutex // for rows.Next() { // var departureAddress []byte // var destinationAddress []byte // var booking internal.Booking // if err := rows.Scan(&booking.ID, &booking.Passenger.ID, &booking.Driver.ID, &booking.Status, &departureAddress, &destinationAddress, &booking.Pickup_date, &booking.Duration, &booking.Distance); err != nil { // return nil, err // } // wg.Add(1) // go func(booking internal.Booking, departureAddress, destinationAddress []byte) { // defer wg.Done() // // Common logic for both "driver" and "passenger" cases // booking, err := s.populateBookingDetails(booking, departureAddress, destinationAddress) // if err != nil { // mu.Lock() // err = fmt.Errorf("Error populating booking details: %w", err) // mu.Unlock() // return // } // mu.Lock() // bookings = append(bookings, booking) // mu.Unlock() // }(booking, departureAddress, destinationAddress) // } // Wait for all goroutines to finish wg.Wait() // if err := rows.Err(); err != nil { // return nil, err // } return bookings, nil } func (s MongoDBStorage) populateBookingDetails(booking internal.Booking, departureAddress, destinationAddress []byte) (internal.Booking, error) { var wg sync.WaitGroup var mu sync.Mutex errCh := make(chan error, 4) // Buffered channel to handle potential errors // Concurrently fetch passenger information wg.Add(1) go func() { defer wg.Done() passenger, err := s.GetPassenger(booking.Passenger.ID) if err != nil { errCh <- fmt.Errorf("MongoDB Storage GetBooking Error getting passenger: %w", err) return } mu.Lock() booking.Passenger = passenger.Passenger mu.Unlock() }() // Concurrently fetch driver information wg.Add(1) go func() { defer wg.Done() driver, err := s.GetDriver(booking.Driver.ID) if err != nil { errCh <- fmt.Errorf("MongoDB Storage GetBooking Error getting driver: %w", err) return } mu.Lock() booking.Driver = driver.Driver mu.Unlock() }() // Concurrently decode departureAddress into GeoJSON wg.Add(1) go func() { defer wg.Done() decodedDepartureAddress, err := geojson.UnmarshalFeature(departureAddress) if err != nil { errCh <- fmt.Errorf("MongoDB Storage FilterBookingsByStatus Error decoding Driver departure route into GeoJSON: %w", err) return } mu.Lock() booking.PassengerPickupAddress = decodedDepartureAddress mu.Unlock() }() // Concurrently decode destinationAddress into GeoJSON wg.Add(1) go func() { defer wg.Done() decodedDestinationAddress, err := geojson.UnmarshalFeature(destinationAddress) if err != nil { errCh <- fmt.Errorf("MongoDB Storage FilterBookingsByStatus Error decoding Driver destination route into GeoJSON: %w", err) return } mu.Lock() booking.PassengerDropAddress = decodedDestinationAddress mu.Unlock() }() // Close the error channel after all goroutines are done go func() { wg.Wait() close(errCh) }() // Check for errors using a select statement for err := range errCh { return internal.Booking{}, err // Return the first error encountered } return booking, nil } func (s MongoDBStorage) GetAllDrivers( date int64) (drivers []internal.Driver, err error) { // rows := s.Client.Database(s.DbName).Collection(s.Collections["users"]) if err != nil { return nil, err } // defer rows.Close() //for rows.Next(ctx) { var driver internal.Driver var departureRoute []byte var preferencesJSON []byte var availabilitiesJSON []byte var carJSON []byte // if err := rows.Scan( // &driver.Driver.ID, // &departureRoute, // &driver.Radius, // &driver.Driver.LastName, // &driver.Driver.FirstName, // &driver.Driver.Grade, // &driver.Driver.Alias, // &driver.Driver.Picture, // &driver.Driver.VerifiedIdentity, // &preferencesJSON, // &driver.AvailabilitiesType, // &availabilitiesJSON, // &driver.Driver.Operator, // &carJSON, // ); err != nil { // return nil, err // } if err := json.Unmarshal(departureRoute, &driver.Driver_departure_address); err != nil { return nil, err } if err := json.Unmarshal(preferencesJSON, &driver.Preferences); err != nil { return nil, err } if err := json.Unmarshal(carJSON, &driver.Car); err != nil { return nil, err } // Filter drivers based on date and time matching punctual or regular availabilities. if driver.AvailabilitiesType == internal.Punctual { if err := json.Unmarshal(availabilitiesJSON, &driver.PunctualAvailabilities); err != nil { return nil, err } year, month, day := time.Unix(date, 0).Date() dateHour := time.Unix(date, 0).UTC().Local() dateHour_string := dateHour.Format("3:04 PM") for _, avail := range driver.PunctualAvailabilities { availyear, availmonth, availday := time.Unix(avail.Date, 0).Date() if availyear == year && availmonth == month && availday == day { startTime, err := time.Parse("3:04 PM", avail.StartTime) if err != nil { return nil, err } endTime, err := time.Parse("3:04 PM", avail.EndTime) if err != nil { return nil, err } // Convert DateHour_string to time.Time dateHourTime, err := time.Parse("3:04 PM", dateHour_string) if err != nil { return nil, err } if dateHourTime.After(startTime) || dateHourTime.Equal(startTime) { if dateHourTime.Before(endTime) || dateHourTime.Equal(endTime) { drivers = append(drivers, driver) } } } // Check if the date and time match the punctual driver's availability. } } else if driver.AvailabilitiesType == internal.Regular { if err := json.Unmarshal(availabilitiesJSON, &driver.RegularAvailabilities); err != nil { return nil, err } dayOfWeek := strings.ToLower(time.Unix(date, 0).Local().Format("Mon")) dateHour := time.Unix(date, 0).UTC().Local() dateHour_string := dateHour.Format("3:04 PM") for _, avail := range driver.RegularAvailabilities { // Check if the day and time match the regular driver's availability. if strings.ToLower(avail.DayOfWeek) == dayOfWeek { startTime, err := time.Parse("3:04 PM", avail.StartTime) if err != nil { return nil, err } endTime, err := time.Parse("3:04 PM", avail.EndTime) if err != nil { return nil, err } // Convert DateHour_string to time.Time dateHourTime, err := time.Parse("3:04 PM", dateHour_string) if err != nil { return nil, err } if dateHourTime.After(startTime) || dateHourTime.Equal(startTime) { if dateHourTime.Before(endTime) || dateHourTime.Equal(endTime) { drivers = append(drivers, driver) } } } } } //} // if err := rows.Err(); err != nil { // return nil, err // } return drivers, nil } func (s MongoDBStorage) DriverJourneys(departure_route *geojson.Feature, departure_date int64) (drivers []internal.Driver, err error) { allDrivers, err := s.GetAllDrivers(departure_date) if err != nil { return nil, err } for _, driver := range allDrivers { // Check if the departure route is the same as the driver's departure route. if departure_route.Point().Y() == driver.Driver_departure_address.Point().Y() && departure_route.Point().X() == driver.Driver_departure_address.Point().X() { drivers = append(drivers, driver) } else { // Calculate the distance between the departure point and the driver's departure route. coords1 := departure_route.Geometry.(orb.Point) coords2 := driver.Driver_departure_address.Geometry.(orb.Point) distance := utils.Haversine(coords1[1], coords1[0], coords2[1], coords2[0]) if int64(distance) <= int64(driver.Radius) { drivers = append(drivers, driver) } } } return drivers, nil }