Your Question

My two types are below. I would like to return the user plus its known last latitude and longitude and nothing else. However, I am struggling to do this and the best I have right now is the following that returns everything in the embedded location.

database.DB.Debug().Preload("Locations").Where("user_id = ?", uid).Find(&users)

How do I get this to work properly? All attempts to select from the location object are just producing null, e.g.

database.DB.Debug().Preload("Locations").Where("user_id = ?", uid).Select('user.id, locations.latitude').Find(&users)

type Location struct {
    gorm.Model
    UserID string    `json:"userId"`
    User   User  `gorm:"foreignKey:userID;references:Id"`
    Latitude   float64   `json:"latitude"`
    Longitude  float64   `json:"longitude"`
    RecordedAt time.Time `json:"recordedAt,omitempty"`
}

type User struct {
    gorm.Model
    Id       string    `gorm:"type:uuid;primaryKey" json:"id"`
    Name     string    `json:"name"`
    Email    string    `json:"email;unique"`
    Locations               []Location `json:"locations"`
}

The document you expected this should be explained

Expected answer

I expected that I'd get back select arguments from locations and users.

Comment From: black-06

type Location struct {
    ID         uint64
    UserID     uint64
    Latitude   float64
    Longitude  float64
    RecordedAt time.Time
}

type User struct {
    ID        uint64
    Name      string
    Email     string
    Locations []Location
}

func TestSelectPerload(t *testing.T) {
    db := GetConn()

    db.Migrator().DropTable(&Location{}, &User{})
    db.AutoMigrate(&Location{}, &User{})

    db.Create(&User{
        ID:    1,
        Name:  "foo",
        Email: "bar",
        Locations: []Location{
            {ID: 1, Latitude: 1.1, Longitude: 1.2, RecordedAt: time.Date(2001, 1, 1, 0, 0, 0, 0, time.UTC)},
            {ID: 2, Latitude: 2.1, Longitude: 2.2, RecordedAt: time.Date(2002, 1, 1, 0, 0, 0, 0, time.UTC)},
            {ID: 3, Latitude: 3.1, Longitude: 3.2, RecordedAt: time.Date(2003, 1, 1, 0, 0, 0, 0, time.UTC)},
        },
    })

    lastLocation := func(tx *gorm.DB) *gorm.DB {
        return tx.Select("user_id", "latitude").Order("recorded_at DESC").Limit(1)
    }

    var user User
    db.Preload("Locations", lastLocation).Where("id = ?", 1).Select("id").Find(&user)

    assert.Equal(t, User{
        ID: 1,
        Locations: []Location{
            {UserID: 1, Latitude: 3.1},
        },
    }, user)
}

Comment From: cinjon

That's not working. I am also getting back other fields, both those from the gorm.Model (updatedAt, deletedAt) as well as my own isBirth. I'll try to put up a playground.

"locations":[{"ID":0,"CreatedAt":"0001-01-01T00:00:00Z","UpdatedAt":"0001-01-01T00:00:00Z","DeletedAt":null,"userId":1,"latitude":3.21,"longitude":11.22,"recordedAt":"0001-01-01T00:00:00Z","isBirth":false}]

func GetStaticUsers(c *gin.Context) {
    lastLocation := func(tx *gorm.DB) *gorm.DB {
        return tx.Select("user_id", "latitude", "longitude").Order("recorded_at DESC").Limit(1)
    }

    var users []models.User
    if err := database.DB.Preload("Locations", lastLocation).Where("is_static = ?", true).Select("id").Find(&users).Error; err != nil {
        c.JSON(http.StatusNotFound, gin.H{"status": "error", "message": "No static users found"})
    } else {
        c.JSON(http.StatusOK, gin.H{
            "status":    "success",
            "users": users,
        })
    }
}
type User struct {
    gorm.Model
    Name                    string     `json:"name"`
    Locations               []Location `json:"locations"`
    NumSimultaneousMeetings int        `json:"numSimultaneousMeetings"`
    IsStatic                bool       `json:"isStatic"`
}

type Location struct {
    gorm.Model
    UserID uint `json:"userId"`
    Latitude   float64   `json:"latitude"`
    Longitude  float64   `json:"longitude"`
    RecordedAt time.Time `json:"recordedAt,omitempty"`
    IsBirth    bool      `json:"isBirth"`
}

Comment From: cinjon

It also doesn't work with many users, e.g.

    lastLocation := func(tx *gorm.DB) *gorm.DB {
        return tx.Select("user_id", "latitude", "longitude").Order("recorded_at DESC").Limit(1)
    }

    var users []models.User
    if err := r.Database.Debug().Preload("Locations").Find(&users).Error; err != nil {
        return nil, fmt.Errorf("Cannot get static users")
    }

Returns only the most recent location of the last found user.

Comment From: github-actions[bot]

This issue has been automatically marked as stale because it has been open 360 days with no activity. Remove stale label or comment or this will be closed in 180 days