Add precalc h3 cells to fieldseeker tables

This makes it so we don't have to try to parse the geometry JSON and
instead can just pass pre-calculated h3 values, which take fewer bytes,
everywhere.
This commit is contained in:
Eli Ribble 2026-01-05 23:25:16 +00:00
parent 2e74f95e8c
commit b542b8268e
21 changed files with 353 additions and 62 deletions

View file

@ -1088,18 +1088,20 @@ func updateSummaryTables(ctx context.Context, org *models.Organization) {
log.Info().Int("resolution", i).Msg("Working summary layer")
cellToCount := make(map[h3.Cell]int, 0)
for _, p := range point_locations {
p, err := getPoint(p.Geometry)
if p.H3cell.IsNull() {
continue
}
cell, err := toH3Cell(p.H3cell.MustGet())
if err != nil {
log.Error().Err(err).Msg("Failed to get geometry point")
continue
}
cell, err := h3.LatLngToCell(p, i)
scaled, err := cell.Parent(i)
if err != nil {
log.Error().Err(err).Msg("Failed to get cell")
log.Error().Err(err).Int("resolution", i).Msg("Failed to get cell's parent at resolution")
continue
}
//log.Info().Float64("X", p.GeometryX).Float64("Y", p.GeometryY).Str("cell", cell.String()).Msg("Converted lat/lng")
cellToCount[cell] = cellToCount[cell] + 1
cellToCount[scaled] = cellToCount[scaled] + 1
}
var to_insert []bob.Mod[*dialect.InsertQuery] = make([]bob.Mod[*dialect.InsertQuery], 0)
to_insert = append(to_insert, im.Into("h3_aggregation", "cell", "resolution", "count_", "type_", "organization_id", "geometry"))
@ -1620,5 +1622,3 @@ func exportFieldseekerLayer(ctx context.Context, org *models.Organization, fssyn
log.Info().Uint("inserts", stats.Inserts).Uint("updates", stats.Updates).Uint("no change", stats.Unchanged).Str("layer", layer.Name).Msg("Finished layer")
return stats, nil
}

View file

@ -447,6 +447,15 @@ var FieldseekerPointlocations = Table[
Generated: false,
AutoIncr: false,
},
H3cell: column{
Name: "h3cell",
DBType: "h3index",
Default: "GENERATED",
Comment: "",
Nullable: true,
Generated: true,
AutoIncr: false,
},
},
Indexes: fieldseekerPointlocationIndexes{
PointlocationPkey: index{
@ -541,11 +550,12 @@ type fieldseekerPointlocationColumns struct {
Geospatial column
Version column
OrganizationID column
H3cell column
}
func (c fieldseekerPointlocationColumns) AsSlice() []column {
return []column{
c.Objectid, c.Name, c.Zone, c.Habitat, c.Priority, c.Usetype, c.Active, c.Description, c.Accessdesc, c.Comments, c.Symbology, c.Externalid, c.Nextactiondatescheduled, c.Larvinspectinterval, c.Zone2, c.Locationnumber, c.Globalid, c.Stype, c.Lastinspectdate, c.Lastinspectbreeding, c.Lastinspectavglarvae, c.Lastinspectavgpupae, c.Lastinspectlstages, c.Lastinspectactiontaken, c.Lastinspectfieldspecies, c.Lasttreatdate, c.Lasttreatproduct, c.Lasttreatqty, c.Lasttreatqtyunit, c.Lastinspectactivity, c.Lasttreatactivity, c.Lastinspectconditions, c.Waterorigin, c.X, c.Y, c.Assignedtech, c.Creationdate, c.Creator, c.Editdate, c.Editor, c.Jurisdiction, c.DeactivateReason, c.Scalarpriority, c.Sourcestatus, c.Geometry, c.Geospatial, c.Version, c.OrganizationID,
c.Objectid, c.Name, c.Zone, c.Habitat, c.Priority, c.Usetype, c.Active, c.Description, c.Accessdesc, c.Comments, c.Symbology, c.Externalid, c.Nextactiondatescheduled, c.Larvinspectinterval, c.Zone2, c.Locationnumber, c.Globalid, c.Stype, c.Lastinspectdate, c.Lastinspectbreeding, c.Lastinspectavglarvae, c.Lastinspectavgpupae, c.Lastinspectlstages, c.Lastinspectactiontaken, c.Lastinspectfieldspecies, c.Lasttreatdate, c.Lasttreatproduct, c.Lasttreatqty, c.Lasttreatqtyunit, c.Lastinspectactivity, c.Lasttreatactivity, c.Lastinspectconditions, c.Waterorigin, c.X, c.Y, c.Assignedtech, c.Creationdate, c.Creator, c.Editdate, c.Editor, c.Jurisdiction, c.DeactivateReason, c.Scalarpriority, c.Sourcestatus, c.Geometry, c.Geospatial, c.Version, c.OrganizationID, c.H3cell,
}
}

View file

@ -825,6 +825,15 @@ var FieldseekerServicerequests = Table[
Generated: false,
AutoIncr: false,
},
H3cell: column{
Name: "h3cell",
DBType: "h3index",
Default: "GENERATED",
Comment: "",
Nullable: true,
Generated: true,
AutoIncr: false,
},
},
Indexes: fieldseekerServicerequestIndexes{
ServicerequestPkey: index{
@ -961,11 +970,12 @@ type fieldseekerServicerequestColumns struct {
Geospatial column
Version column
OrganizationID column
H3cell column
}
func (c fieldseekerServicerequestColumns) AsSlice() []column {
return []column{
c.Objectid, c.Recdatetime, c.Source, c.Entrytech, c.Priority, c.Supervisor, c.Assignedtech, c.Status, c.Clranon, c.Clrfname, c.Clrphone1, c.Clrphone2, c.Clremail, c.Clrcompany, c.Clraddr1, c.Clraddr2, c.Clrcity, c.Clrstate, c.Clrzip, c.Clrother, c.Clrcontpref, c.Reqcompany, c.Reqaddr1, c.Reqaddr2, c.Reqcity, c.Reqstate, c.Reqzip, c.Reqcrossst, c.Reqsubdiv, c.Reqmapgrid, c.Reqpermission, c.Reqtarget, c.Reqdescr, c.Reqnotesfortech, c.Reqnotesforcust, c.Reqfldnotes, c.Reqprogramactions, c.Datetimeclosed, c.Techclosed, c.SRNumber, c.Reviewed, c.Reviewedby, c.Revieweddate, c.Accepted, c.Accepteddate, c.Rejectedby, c.Rejecteddate, c.Rejectedreason, c.Duedate, c.Acceptedby, c.Comments, c.Estcompletedate, c.Nextaction, c.Recordstatus, c.Globalid, c.CreatedUser, c.CreatedDate, c.LastEditedUser, c.LastEditedDate, c.Firstresponsedate, c.Responsedaycount, c.Allowed, c.Xvalue, c.Yvalue, c.Validx, c.Validy, c.Externalid, c.Externalerror, c.Pointlocid, c.Notified, c.Notifieddate, c.Scheduled, c.Scheduleddate, c.Dog, c.SchedulePeriod, c.ScheduleNotes, c.Spanish, c.Creationdate, c.Creator, c.Editdate, c.Editor, c.Issuesreported, c.Jurisdiction, c.Notificationtimestamp, c.Zone, c.Zone2, c.Geometry, c.Geospatial, c.Version, c.OrganizationID,
c.Objectid, c.Recdatetime, c.Source, c.Entrytech, c.Priority, c.Supervisor, c.Assignedtech, c.Status, c.Clranon, c.Clrfname, c.Clrphone1, c.Clrphone2, c.Clremail, c.Clrcompany, c.Clraddr1, c.Clraddr2, c.Clrcity, c.Clrstate, c.Clrzip, c.Clrother, c.Clrcontpref, c.Reqcompany, c.Reqaddr1, c.Reqaddr2, c.Reqcity, c.Reqstate, c.Reqzip, c.Reqcrossst, c.Reqsubdiv, c.Reqmapgrid, c.Reqpermission, c.Reqtarget, c.Reqdescr, c.Reqnotesfortech, c.Reqnotesforcust, c.Reqfldnotes, c.Reqprogramactions, c.Datetimeclosed, c.Techclosed, c.SRNumber, c.Reviewed, c.Reviewedby, c.Revieweddate, c.Accepted, c.Accepteddate, c.Rejectedby, c.Rejecteddate, c.Rejectedreason, c.Duedate, c.Acceptedby, c.Comments, c.Estcompletedate, c.Nextaction, c.Recordstatus, c.Globalid, c.CreatedUser, c.CreatedDate, c.LastEditedUser, c.LastEditedDate, c.Firstresponsedate, c.Responsedaycount, c.Allowed, c.Xvalue, c.Yvalue, c.Validx, c.Validy, c.Externalid, c.Externalerror, c.Pointlocid, c.Notified, c.Notifieddate, c.Scheduled, c.Scheduleddate, c.Dog, c.SchedulePeriod, c.ScheduleNotes, c.Spanish, c.Creationdate, c.Creator, c.Editdate, c.Editor, c.Issuesreported, c.Jurisdiction, c.Notificationtimestamp, c.Zone, c.Zone2, c.Geometry, c.Geospatial, c.Version, c.OrganizationID, c.H3cell,
}
}

View file

@ -429,6 +429,15 @@ var FieldseekerTrapdata = Table[
Generated: false,
AutoIncr: false,
},
H3cell: column{
Name: "h3cell",
DBType: "h3index",
Default: "GENERATED",
Comment: "",
Nullable: true,
Generated: true,
AutoIncr: false,
},
},
Indexes: fieldseekerTrapdatumIndexes{
TrapdataPkey: index{
@ -521,11 +530,12 @@ type fieldseekerTrapdatumColumns struct {
Geospatial column
Version column
OrganizationID column
H3cell column
}
func (c fieldseekerTrapdatumColumns) AsSlice() []column {
return []column{
c.Objectid, c.Traptype, c.Trapactivitytype, c.Startdatetime, c.Enddatetime, c.Comments, c.Idbytech, c.Sortbytech, c.Processed, c.Sitecond, c.Locationname, c.Recordstatus, c.Reviewed, c.Reviewedby, c.Revieweddate, c.Trapcondition, c.Trapnights, c.Zone, c.Zone2, c.Globalid, c.CreatedUser, c.CreatedDate, c.LastEditedUser, c.LastEditedDate, c.Srid, c.Fieldtech, c.Gatewaysync, c.LocID, c.Voltage, c.Winddir, c.Windspeed, c.Avetemp, c.Raingauge, c.LR, c.Field, c.Vectorsurvtrapdataid, c.Vectorsurvtraplocationid, c.Creationdate, c.Creator, c.Editdate, c.Editor, c.Lure, c.Geometry, c.Geospatial, c.Version, c.OrganizationID,
c.Objectid, c.Traptype, c.Trapactivitytype, c.Startdatetime, c.Enddatetime, c.Comments, c.Idbytech, c.Sortbytech, c.Processed, c.Sitecond, c.Locationname, c.Recordstatus, c.Reviewed, c.Reviewedby, c.Revieweddate, c.Trapcondition, c.Trapnights, c.Zone, c.Zone2, c.Globalid, c.CreatedUser, c.CreatedDate, c.LastEditedUser, c.LastEditedDate, c.Srid, c.Fieldtech, c.Gatewaysync, c.LocID, c.Voltage, c.Winddir, c.Windspeed, c.Avetemp, c.Raingauge, c.LR, c.Field, c.Vectorsurvtrapdataid, c.Vectorsurvtraplocationid, c.Creationdate, c.Creator, c.Editdate, c.Editor, c.Lure, c.Geometry, c.Geospatial, c.Version, c.OrganizationID, c.H3cell,
}
}

View file

@ -537,6 +537,15 @@ var FieldseekerTreatments = Table[
Generated: false,
AutoIncr: false,
},
H3cell: column{
Name: "h3cell",
DBType: "h3index",
Default: "GENERATED",
Comment: "",
Nullable: true,
Generated: true,
AutoIncr: false,
},
},
Indexes: fieldseekerTreatmentIndexes{
TreatmentPkey: index{
@ -641,11 +650,12 @@ type fieldseekerTreatmentColumns struct {
Geospatial column
Version column
OrganizationID column
H3cell column
}
func (c fieldseekerTreatmentColumns) AsSlice() []column {
return []column{
c.Objectid, c.Activity, c.Treatarea, c.Areaunit, c.Product, c.Qty, c.Qtyunit, c.Method, c.Equiptype, c.Comments, c.Avetemp, c.Windspeed, c.Winddir, c.Raingauge, c.Startdatetime, c.Enddatetime, c.InspID, c.Reviewed, c.Reviewedby, c.Revieweddate, c.Locationname, c.Zone, c.Warningoverride, c.Recordstatus, c.Zone2, c.Treatacres, c.Tirecount, c.Cbcount, c.Containercount, c.Globalid, c.Treatmentlength, c.Treatmenthours, c.Treatmentlengthunits, c.Linelocid, c.Pointlocid, c.Polygonlocid, c.Srid, c.Sdid, c.Barrierrouteid, c.Ulvrouteid, c.Fieldtech, c.Ptaid, c.Flowrate, c.Habitat, c.Treathectares, c.Invloc, c.TempSitecond, c.Sitecond, c.Totalcostprodcut, c.Creationdate, c.Creator, c.Editdate, c.Editor, c.Targetspecies, c.Geometry, c.Geospatial, c.Version, c.OrganizationID,
c.Objectid, c.Activity, c.Treatarea, c.Areaunit, c.Product, c.Qty, c.Qtyunit, c.Method, c.Equiptype, c.Comments, c.Avetemp, c.Windspeed, c.Winddir, c.Raingauge, c.Startdatetime, c.Enddatetime, c.InspID, c.Reviewed, c.Reviewedby, c.Revieweddate, c.Locationname, c.Zone, c.Warningoverride, c.Recordstatus, c.Zone2, c.Treatacres, c.Tirecount, c.Cbcount, c.Containercount, c.Globalid, c.Treatmentlength, c.Treatmenthours, c.Treatmentlengthunits, c.Linelocid, c.Pointlocid, c.Polygonlocid, c.Srid, c.Sdid, c.Barrierrouteid, c.Ulvrouteid, c.Fieldtech, c.Ptaid, c.Flowrate, c.Habitat, c.Treathectares, c.Invloc, c.TempSitecond, c.Sitecond, c.Totalcostprodcut, c.Creationdate, c.Creator, c.Editdate, c.Editor, c.Targetspecies, c.Geometry, c.Geospatial, c.Version, c.OrganizationID, c.H3cell,
}
}

View file

@ -585,6 +585,7 @@ func (f *Factory) FromExistingFieldseekerPointlocation(m *models.FieldseekerPoin
o.Geospatial = func() null.Val[string] { return m.Geospatial }
o.Version = func() int32 { return m.Version }
o.OrganizationID = func() int32 { return m.OrganizationID }
o.H3cell = func() null.Val[string] { return m.H3cell }
ctx := context.Background()
if m.R.Organization != nil {
@ -1238,6 +1239,7 @@ func (f *Factory) FromExistingFieldseekerServicerequest(m *models.FieldseekerSer
o.Geospatial = func() null.Val[string] { return m.Geospatial }
o.Version = func() int32 { return m.Version }
o.OrganizationID = func() int32 { return m.OrganizationID }
o.H3cell = func() null.Val[string] { return m.H3cell }
ctx := context.Background()
if m.R.Organization != nil {
@ -1484,6 +1486,7 @@ func (f *Factory) FromExistingFieldseekerTrapdatum(m *models.FieldseekerTrapdatu
o.Geospatial = func() null.Val[string] { return m.Geospatial }
o.Version = func() int32 { return m.Version }
o.OrganizationID = func() int32 { return m.OrganizationID }
o.H3cell = func() null.Val[string] { return m.H3cell }
ctx := context.Background()
if m.R.Organization != nil {
@ -1632,6 +1635,7 @@ func (f *Factory) FromExistingFieldseekerTreatment(m *models.FieldseekerTreatmen
o.Geospatial = func() null.Val[string] { return m.Geospatial }
o.Version = func() int32 { return m.Version }
o.OrganizationID = func() int32 { return m.OrganizationID }
o.H3cell = func() null.Val[string] { return m.H3cell }
ctx := context.Background()
if m.R.Organization != nil {

View file

@ -88,6 +88,7 @@ type FieldseekerPointlocationTemplate struct {
Geospatial func() null.Val[string]
Version func() int32
OrganizationID func() int32
H3cell func() null.Val[string]
r fieldseekerPointlocationR
f *Factory
@ -484,6 +485,9 @@ func (o FieldseekerPointlocationTemplate) Build() *models.FieldseekerPointlocati
if o.OrganizationID != nil {
m.OrganizationID = o.OrganizationID()
}
if o.H3cell != nil {
m.H3cell = o.H3cell()
}
o.setModelRels(m)
@ -683,6 +687,7 @@ func (m fieldseekerPointlocationMods) RandomizeAllColumns(f *faker.Faker) Fields
FieldseekerPointlocationMods.RandomGeospatial(f),
FieldseekerPointlocationMods.RandomVersion(f),
FieldseekerPointlocationMods.RandomOrganizationID(f),
FieldseekerPointlocationMods.RandomH3cell(f),
}
}
@ -3120,6 +3125,59 @@ func (m fieldseekerPointlocationMods) RandomOrganizationID(f *faker.Faker) Field
})
}
// Set the model columns to this value
func (m fieldseekerPointlocationMods) H3cell(val null.Val[string]) FieldseekerPointlocationMod {
return FieldseekerPointlocationModFunc(func(_ context.Context, o *FieldseekerPointlocationTemplate) {
o.H3cell = func() null.Val[string] { return val }
})
}
// Set the Column from the function
func (m fieldseekerPointlocationMods) H3cellFunc(f func() null.Val[string]) FieldseekerPointlocationMod {
return FieldseekerPointlocationModFunc(func(_ context.Context, o *FieldseekerPointlocationTemplate) {
o.H3cell = f
})
}
// Clear any values for the column
func (m fieldseekerPointlocationMods) UnsetH3cell() FieldseekerPointlocationMod {
return FieldseekerPointlocationModFunc(func(_ context.Context, o *FieldseekerPointlocationTemplate) {
o.H3cell = nil
})
}
// Generates a random value for the column using the given faker
// if faker is nil, a default faker is used
// The generated value is sometimes null
func (m fieldseekerPointlocationMods) RandomH3cell(f *faker.Faker) FieldseekerPointlocationMod {
return FieldseekerPointlocationModFunc(func(_ context.Context, o *FieldseekerPointlocationTemplate) {
o.H3cell = func() null.Val[string] {
if f == nil {
f = &defaultFaker
}
val := random_string(f)
return null.From(val)
}
})
}
// Generates a random value for the column using the given faker
// if faker is nil, a default faker is used
// The generated value is never null
func (m fieldseekerPointlocationMods) RandomH3cellNotNull(f *faker.Faker) FieldseekerPointlocationMod {
return FieldseekerPointlocationModFunc(func(_ context.Context, o *FieldseekerPointlocationTemplate) {
o.H3cell = func() null.Val[string] {
if f == nil {
f = &defaultFaker
}
val := random_string(f)
return null.From(val)
}
})
}
func (m fieldseekerPointlocationMods) WithParentsCascading() FieldseekerPointlocationMod {
return FieldseekerPointlocationModFunc(func(ctx context.Context, o *FieldseekerPointlocationTemplate) {
if isDone, _ := fieldseekerPointlocationWithParentsCascadingCtx.Value(ctx); isDone {

View file

@ -130,6 +130,7 @@ type FieldseekerServicerequestTemplate struct {
Geospatial func() null.Val[string]
Version func() int32
OrganizationID func() int32
H3cell func() null.Val[string]
r fieldseekerServicerequestR
f *Factory
@ -820,6 +821,9 @@ func (o FieldseekerServicerequestTemplate) Build() *models.FieldseekerServicereq
if o.OrganizationID != nil {
m.OrganizationID = o.OrganizationID()
}
if o.H3cell != nil {
m.H3cell = o.H3cell()
}
o.setModelRels(m)
@ -1061,6 +1065,7 @@ func (m fieldseekerServicerequestMods) RandomizeAllColumns(f *faker.Faker) Field
FieldseekerServicerequestMods.RandomGeospatial(f),
FieldseekerServicerequestMods.RandomVersion(f),
FieldseekerServicerequestMods.RandomOrganizationID(f),
FieldseekerServicerequestMods.RandomH3cell(f),
}
}
@ -5724,6 +5729,59 @@ func (m fieldseekerServicerequestMods) RandomOrganizationID(f *faker.Faker) Fiel
})
}
// Set the model columns to this value
func (m fieldseekerServicerequestMods) H3cell(val null.Val[string]) FieldseekerServicerequestMod {
return FieldseekerServicerequestModFunc(func(_ context.Context, o *FieldseekerServicerequestTemplate) {
o.H3cell = func() null.Val[string] { return val }
})
}
// Set the Column from the function
func (m fieldseekerServicerequestMods) H3cellFunc(f func() null.Val[string]) FieldseekerServicerequestMod {
return FieldseekerServicerequestModFunc(func(_ context.Context, o *FieldseekerServicerequestTemplate) {
o.H3cell = f
})
}
// Clear any values for the column
func (m fieldseekerServicerequestMods) UnsetH3cell() FieldseekerServicerequestMod {
return FieldseekerServicerequestModFunc(func(_ context.Context, o *FieldseekerServicerequestTemplate) {
o.H3cell = nil
})
}
// Generates a random value for the column using the given faker
// if faker is nil, a default faker is used
// The generated value is sometimes null
func (m fieldseekerServicerequestMods) RandomH3cell(f *faker.Faker) FieldseekerServicerequestMod {
return FieldseekerServicerequestModFunc(func(_ context.Context, o *FieldseekerServicerequestTemplate) {
o.H3cell = func() null.Val[string] {
if f == nil {
f = &defaultFaker
}
val := random_string(f)
return null.From(val)
}
})
}
// Generates a random value for the column using the given faker
// if faker is nil, a default faker is used
// The generated value is never null
func (m fieldseekerServicerequestMods) RandomH3cellNotNull(f *faker.Faker) FieldseekerServicerequestMod {
return FieldseekerServicerequestModFunc(func(_ context.Context, o *FieldseekerServicerequestTemplate) {
o.H3cell = func() null.Val[string] {
if f == nil {
f = &defaultFaker
}
val := random_string(f)
return null.From(val)
}
})
}
func (m fieldseekerServicerequestMods) WithParentsCascading() FieldseekerServicerequestMod {
return FieldseekerServicerequestModFunc(func(ctx context.Context, o *FieldseekerServicerequestTemplate) {
if isDone, _ := fieldseekerServicerequestWithParentsCascadingCtx.Value(ctx); isDone {

View file

@ -86,6 +86,7 @@ type FieldseekerTrapdatumTemplate struct {
Geospatial func() null.Val[string]
Version func() int32
OrganizationID func() int32
H3cell func() null.Val[string]
r fieldseekerTrapdatumR
f *Factory
@ -468,6 +469,9 @@ func (o FieldseekerTrapdatumTemplate) Build() *models.FieldseekerTrapdatum {
if o.OrganizationID != nil {
m.OrganizationID = o.OrganizationID()
}
if o.H3cell != nil {
m.H3cell = o.H3cell()
}
o.setModelRels(m)
@ -665,6 +669,7 @@ func (m fieldseekerTrapdatumMods) RandomizeAllColumns(f *faker.Faker) Fieldseeke
FieldseekerTrapdatumMods.RandomGeospatial(f),
FieldseekerTrapdatumMods.RandomVersion(f),
FieldseekerTrapdatumMods.RandomOrganizationID(f),
FieldseekerTrapdatumMods.RandomH3cell(f),
}
}
@ -2996,6 +3001,59 @@ func (m fieldseekerTrapdatumMods) RandomOrganizationID(f *faker.Faker) Fieldseek
})
}
// Set the model columns to this value
func (m fieldseekerTrapdatumMods) H3cell(val null.Val[string]) FieldseekerTrapdatumMod {
return FieldseekerTrapdatumModFunc(func(_ context.Context, o *FieldseekerTrapdatumTemplate) {
o.H3cell = func() null.Val[string] { return val }
})
}
// Set the Column from the function
func (m fieldseekerTrapdatumMods) H3cellFunc(f func() null.Val[string]) FieldseekerTrapdatumMod {
return FieldseekerTrapdatumModFunc(func(_ context.Context, o *FieldseekerTrapdatumTemplate) {
o.H3cell = f
})
}
// Clear any values for the column
func (m fieldseekerTrapdatumMods) UnsetH3cell() FieldseekerTrapdatumMod {
return FieldseekerTrapdatumModFunc(func(_ context.Context, o *FieldseekerTrapdatumTemplate) {
o.H3cell = nil
})
}
// Generates a random value for the column using the given faker
// if faker is nil, a default faker is used
// The generated value is sometimes null
func (m fieldseekerTrapdatumMods) RandomH3cell(f *faker.Faker) FieldseekerTrapdatumMod {
return FieldseekerTrapdatumModFunc(func(_ context.Context, o *FieldseekerTrapdatumTemplate) {
o.H3cell = func() null.Val[string] {
if f == nil {
f = &defaultFaker
}
val := random_string(f)
return null.From(val)
}
})
}
// Generates a random value for the column using the given faker
// if faker is nil, a default faker is used
// The generated value is never null
func (m fieldseekerTrapdatumMods) RandomH3cellNotNull(f *faker.Faker) FieldseekerTrapdatumMod {
return FieldseekerTrapdatumModFunc(func(_ context.Context, o *FieldseekerTrapdatumTemplate) {
o.H3cell = func() null.Val[string] {
if f == nil {
f = &defaultFaker
}
val := random_string(f)
return null.From(val)
}
})
}
func (m fieldseekerTrapdatumMods) WithParentsCascading() FieldseekerTrapdatumMod {
return FieldseekerTrapdatumModFunc(func(ctx context.Context, o *FieldseekerTrapdatumTemplate) {
if isDone, _ := fieldseekerTrapdatumWithParentsCascadingCtx.Value(ctx); isDone {

View file

@ -98,6 +98,7 @@ type FieldseekerTreatmentTemplate struct {
Geospatial func() null.Val[string]
Version func() int32
OrganizationID func() int32
H3cell func() null.Val[string]
r fieldseekerTreatmentR
f *Factory
@ -564,6 +565,9 @@ func (o FieldseekerTreatmentTemplate) Build() *models.FieldseekerTreatment {
if o.OrganizationID != nil {
m.OrganizationID = o.OrganizationID()
}
if o.H3cell != nil {
m.H3cell = o.H3cell()
}
o.setModelRels(m)
@ -773,6 +777,7 @@ func (m fieldseekerTreatmentMods) RandomizeAllColumns(f *faker.Faker) Fieldseeke
FieldseekerTreatmentMods.RandomGeospatial(f),
FieldseekerTreatmentMods.RandomVersion(f),
FieldseekerTreatmentMods.RandomOrganizationID(f),
FieldseekerTreatmentMods.RandomH3cell(f),
}
}
@ -3740,6 +3745,59 @@ func (m fieldseekerTreatmentMods) RandomOrganizationID(f *faker.Faker) Fieldseek
})
}
// Set the model columns to this value
func (m fieldseekerTreatmentMods) H3cell(val null.Val[string]) FieldseekerTreatmentMod {
return FieldseekerTreatmentModFunc(func(_ context.Context, o *FieldseekerTreatmentTemplate) {
o.H3cell = func() null.Val[string] { return val }
})
}
// Set the Column from the function
func (m fieldseekerTreatmentMods) H3cellFunc(f func() null.Val[string]) FieldseekerTreatmentMod {
return FieldseekerTreatmentModFunc(func(_ context.Context, o *FieldseekerTreatmentTemplate) {
o.H3cell = f
})
}
// Clear any values for the column
func (m fieldseekerTreatmentMods) UnsetH3cell() FieldseekerTreatmentMod {
return FieldseekerTreatmentModFunc(func(_ context.Context, o *FieldseekerTreatmentTemplate) {
o.H3cell = nil
})
}
// Generates a random value for the column using the given faker
// if faker is nil, a default faker is used
// The generated value is sometimes null
func (m fieldseekerTreatmentMods) RandomH3cell(f *faker.Faker) FieldseekerTreatmentMod {
return FieldseekerTreatmentModFunc(func(_ context.Context, o *FieldseekerTreatmentTemplate) {
o.H3cell = func() null.Val[string] {
if f == nil {
f = &defaultFaker
}
val := random_string(f)
return null.From(val)
}
})
}
// Generates a random value for the column using the given faker
// if faker is nil, a default faker is used
// The generated value is never null
func (m fieldseekerTreatmentMods) RandomH3cellNotNull(f *faker.Faker) FieldseekerTreatmentMod {
return FieldseekerTreatmentModFunc(func(_ context.Context, o *FieldseekerTreatmentTemplate) {
o.H3cell = func() null.Val[string] {
if f == nil {
f = &defaultFaker
}
val := random_string(f)
return null.From(val)
}
})
}
func (m fieldseekerTreatmentMods) WithParentsCascading() FieldseekerTreatmentMod {
return FieldseekerTreatmentModFunc(func(ctx context.Context, o *FieldseekerTreatmentTemplate) {
if isDone, _ := fieldseekerTreatmentWithParentsCascadingCtx.Value(ctx); isDone {

View file

@ -1,9 +1,11 @@
-- +goose Up
ALTER TABLE fieldseeker.pointlocation ADD COLUMN h3cell h3index GENERATED ALWAYS AS (h3_latlng_to_cell(geospatial, 15)) STORED;
ALTER TABLE fieldseeker.servicerequest ADD COLUMN h3cell h3index GENERATED ALWAYS AS (h3_latlng_to_cell(geospatial, 15)) STORED;
ALTER TABLE fieldseeker.trapdata ADD COLUMN h3cell h3index GENERATED ALWAYS AS (h3_latlng_to_cell(geospatial, 15)) STORED;
ALTER TABLE fieldseeker.treatment ADD COLUMN h3cell h3index GENERATED ALWAYS AS (h3_latlng_to_cell(geospatial, 15)) STORED;
-- +goose Down
ALTER TABLE fieldseeker.pointlocation DROP COLUMN h3cell;
ALTER TABLE fieldseeker.servicerequest DROP COLUMN h3cell;
ALTER TABLE fieldseeker.trapdata DROP COLUMN h3cell;
ALTER TABLE fieldseeker.treatment DROP COLUMN h3cell;

View file

@ -120,6 +120,7 @@ type FieldseekerPointlocation struct {
Geospatial null.Val[string] `db:"geospatial" `
Version int32 `db:"version,pk" `
OrganizationID int32 `db:"organization_id" `
H3cell null.Val[string] `db:"h3cell,generated" `
R fieldseekerPointlocationR `db:"-" `
}
@ -142,7 +143,7 @@ type fieldseekerPointlocationR struct {
func buildFieldseekerPointlocationColumns(alias string) fieldseekerPointlocationColumns {
return fieldseekerPointlocationColumns{
ColumnsExpr: expr.NewColumnsExpr(
"objectid", "name", "zone", "habitat", "priority", "usetype", "active", "description", "accessdesc", "comments", "symbology", "externalid", "nextactiondatescheduled", "larvinspectinterval", "zone2", "locationnumber", "globalid", "stype", "lastinspectdate", "lastinspectbreeding", "lastinspectavglarvae", "lastinspectavgpupae", "lastinspectlstages", "lastinspectactiontaken", "lastinspectfieldspecies", "lasttreatdate", "lasttreatproduct", "lasttreatqty", "lasttreatqtyunit", "lastinspectactivity", "lasttreatactivity", "lastinspectconditions", "waterorigin", "x", "y", "assignedtech", "creationdate", "creator", "editdate", "editor", "jurisdiction", "deactivate_reason", "scalarpriority", "sourcestatus", "geometry", "geospatial", "version", "organization_id",
"objectid", "name", "zone", "habitat", "priority", "usetype", "active", "description", "accessdesc", "comments", "symbology", "externalid", "nextactiondatescheduled", "larvinspectinterval", "zone2", "locationnumber", "globalid", "stype", "lastinspectdate", "lastinspectbreeding", "lastinspectavglarvae", "lastinspectavgpupae", "lastinspectlstages", "lastinspectactiontaken", "lastinspectfieldspecies", "lasttreatdate", "lasttreatproduct", "lasttreatqty", "lasttreatqtyunit", "lastinspectactivity", "lasttreatactivity", "lastinspectconditions", "waterorigin", "x", "y", "assignedtech", "creationdate", "creator", "editdate", "editor", "jurisdiction", "deactivate_reason", "scalarpriority", "sourcestatus", "geometry", "geospatial", "version", "organization_id", "h3cell",
).WithParent("fieldseeker.pointlocation"),
tableAlias: alias,
Objectid: psql.Quote(alias, "objectid"),
@ -193,6 +194,7 @@ func buildFieldseekerPointlocationColumns(alias string) fieldseekerPointlocation
Geospatial: psql.Quote(alias, "geospatial"),
Version: psql.Quote(alias, "version"),
OrganizationID: psql.Quote(alias, "organization_id"),
H3cell: psql.Quote(alias, "h3cell"),
}
}
@ -247,6 +249,7 @@ type fieldseekerPointlocationColumns struct {
Geospatial psql.Expression
Version psql.Expression
OrganizationID psql.Expression
H3cell psql.Expression
}
func (c fieldseekerPointlocationColumns) Alias() string {
@ -1606,6 +1609,7 @@ type fieldseekerPointlocationWhere[Q psql.Filterable] struct {
Geospatial psql.WhereNullMod[Q, string]
Version psql.WhereMod[Q, int32]
OrganizationID psql.WhereMod[Q, int32]
H3cell psql.WhereNullMod[Q, string]
}
func (fieldseekerPointlocationWhere[Q]) AliasedAs(alias string) fieldseekerPointlocationWhere[Q] {
@ -1662,6 +1666,7 @@ func buildFieldseekerPointlocationWhere[Q psql.Filterable](cols fieldseekerPoint
Geospatial: psql.WhereNull[Q, string](cols.Geospatial),
Version: psql.Where[Q, int32](cols.Version),
OrganizationID: psql.Where[Q, int32](cols.OrganizationID),
H3cell: psql.WhereNull[Q, string](cols.H3cell),
}
}

View file

@ -204,6 +204,7 @@ type FieldseekerServicerequest struct {
Geospatial null.Val[string] `db:"geospatial" `
Version int32 `db:"version,pk" `
OrganizationID int32 `db:"organization_id" `
H3cell null.Val[string] `db:"h3cell,generated" `
R fieldseekerServicerequestR `db:"-" `
}
@ -226,7 +227,7 @@ type fieldseekerServicerequestR struct {
func buildFieldseekerServicerequestColumns(alias string) fieldseekerServicerequestColumns {
return fieldseekerServicerequestColumns{
ColumnsExpr: expr.NewColumnsExpr(
"objectid", "recdatetime", "source", "entrytech", "priority", "supervisor", "assignedtech", "status", "clranon", "clrfname", "clrphone1", "clrphone2", "clremail", "clrcompany", "clraddr1", "clraddr2", "clrcity", "clrstate", "clrzip", "clrother", "clrcontpref", "reqcompany", "reqaddr1", "reqaddr2", "reqcity", "reqstate", "reqzip", "reqcrossst", "reqsubdiv", "reqmapgrid", "reqpermission", "reqtarget", "reqdescr", "reqnotesfortech", "reqnotesforcust", "reqfldnotes", "reqprogramactions", "datetimeclosed", "techclosed", "sr_number", "reviewed", "reviewedby", "revieweddate", "accepted", "accepteddate", "rejectedby", "rejecteddate", "rejectedreason", "duedate", "acceptedby", "comments", "estcompletedate", "nextaction", "recordstatus", "globalid", "created_user", "created_date", "last_edited_user", "last_edited_date", "firstresponsedate", "responsedaycount", "allowed", "xvalue", "yvalue", "validx", "validy", "externalid", "externalerror", "pointlocid", "notified", "notifieddate", "scheduled", "scheduleddate", "dog", "schedule_period", "schedule_notes", "spanish", "creationdate", "creator", "editdate", "editor", "issuesreported", "jurisdiction", "notificationtimestamp", "zone", "zone2", "geometry", "geospatial", "version", "organization_id",
"objectid", "recdatetime", "source", "entrytech", "priority", "supervisor", "assignedtech", "status", "clranon", "clrfname", "clrphone1", "clrphone2", "clremail", "clrcompany", "clraddr1", "clraddr2", "clrcity", "clrstate", "clrzip", "clrother", "clrcontpref", "reqcompany", "reqaddr1", "reqaddr2", "reqcity", "reqstate", "reqzip", "reqcrossst", "reqsubdiv", "reqmapgrid", "reqpermission", "reqtarget", "reqdescr", "reqnotesfortech", "reqnotesforcust", "reqfldnotes", "reqprogramactions", "datetimeclosed", "techclosed", "sr_number", "reviewed", "reviewedby", "revieweddate", "accepted", "accepteddate", "rejectedby", "rejecteddate", "rejectedreason", "duedate", "acceptedby", "comments", "estcompletedate", "nextaction", "recordstatus", "globalid", "created_user", "created_date", "last_edited_user", "last_edited_date", "firstresponsedate", "responsedaycount", "allowed", "xvalue", "yvalue", "validx", "validy", "externalid", "externalerror", "pointlocid", "notified", "notifieddate", "scheduled", "scheduleddate", "dog", "schedule_period", "schedule_notes", "spanish", "creationdate", "creator", "editdate", "editor", "issuesreported", "jurisdiction", "notificationtimestamp", "zone", "zone2", "geometry", "geospatial", "version", "organization_id", "h3cell",
).WithParent("fieldseeker.servicerequest"),
tableAlias: alias,
Objectid: psql.Quote(alias, "objectid"),
@ -319,6 +320,7 @@ func buildFieldseekerServicerequestColumns(alias string) fieldseekerServicereque
Geospatial: psql.Quote(alias, "geospatial"),
Version: psql.Quote(alias, "version"),
OrganizationID: psql.Quote(alias, "organization_id"),
H3cell: psql.Quote(alias, "h3cell"),
}
}
@ -415,6 +417,7 @@ type fieldseekerServicerequestColumns struct {
Geospatial psql.Expression
Version psql.Expression
OrganizationID psql.Expression
H3cell psql.Expression
}
func (c fieldseekerServicerequestColumns) Alias() string {
@ -2656,6 +2659,7 @@ type fieldseekerServicerequestWhere[Q psql.Filterable] struct {
Geospatial psql.WhereNullMod[Q, string]
Version psql.WhereMod[Q, int32]
OrganizationID psql.WhereMod[Q, int32]
H3cell psql.WhereNullMod[Q, string]
}
func (fieldseekerServicerequestWhere[Q]) AliasedAs(alias string) fieldseekerServicerequestWhere[Q] {
@ -2754,6 +2758,7 @@ func buildFieldseekerServicerequestWhere[Q psql.Filterable](cols fieldseekerServ
Geospatial: psql.WhereNull[Q, string](cols.Geospatial),
Version: psql.Where[Q, int32](cols.Version),
OrganizationID: psql.Where[Q, int32](cols.OrganizationID),
H3cell: psql.WhereNull[Q, string](cols.H3cell),
}
}

View file

@ -116,6 +116,7 @@ type FieldseekerTrapdatum struct {
Geospatial null.Val[string] `db:"geospatial" `
Version int32 `db:"version,pk" `
OrganizationID int32 `db:"organization_id" `
H3cell null.Val[string] `db:"h3cell,generated" `
R fieldseekerTrapdatumR `db:"-" `
}
@ -138,7 +139,7 @@ type fieldseekerTrapdatumR struct {
func buildFieldseekerTrapdatumColumns(alias string) fieldseekerTrapdatumColumns {
return fieldseekerTrapdatumColumns{
ColumnsExpr: expr.NewColumnsExpr(
"objectid", "traptype", "trapactivitytype", "startdatetime", "enddatetime", "comments", "idbytech", "sortbytech", "processed", "sitecond", "locationname", "recordstatus", "reviewed", "reviewedby", "revieweddate", "trapcondition", "trapnights", "zone", "zone2", "globalid", "created_user", "created_date", "last_edited_user", "last_edited_date", "srid", "fieldtech", "gatewaysync", "loc_id", "voltage", "winddir", "windspeed", "avetemp", "raingauge", "lr", "field", "vectorsurvtrapdataid", "vectorsurvtraplocationid", "creationdate", "creator", "editdate", "editor", "lure", "geometry", "geospatial", "version", "organization_id",
"objectid", "traptype", "trapactivitytype", "startdatetime", "enddatetime", "comments", "idbytech", "sortbytech", "processed", "sitecond", "locationname", "recordstatus", "reviewed", "reviewedby", "revieweddate", "trapcondition", "trapnights", "zone", "zone2", "globalid", "created_user", "created_date", "last_edited_user", "last_edited_date", "srid", "fieldtech", "gatewaysync", "loc_id", "voltage", "winddir", "windspeed", "avetemp", "raingauge", "lr", "field", "vectorsurvtrapdataid", "vectorsurvtraplocationid", "creationdate", "creator", "editdate", "editor", "lure", "geometry", "geospatial", "version", "organization_id", "h3cell",
).WithParent("fieldseeker.trapdata"),
tableAlias: alias,
Objectid: psql.Quote(alias, "objectid"),
@ -187,6 +188,7 @@ func buildFieldseekerTrapdatumColumns(alias string) fieldseekerTrapdatumColumns
Geospatial: psql.Quote(alias, "geospatial"),
Version: psql.Quote(alias, "version"),
OrganizationID: psql.Quote(alias, "organization_id"),
H3cell: psql.Quote(alias, "h3cell"),
}
}
@ -239,6 +241,7 @@ type fieldseekerTrapdatumColumns struct {
Geospatial psql.Expression
Version psql.Expression
OrganizationID psql.Expression
H3cell psql.Expression
}
func (c fieldseekerTrapdatumColumns) Alias() string {
@ -1556,6 +1559,7 @@ type fieldseekerTrapdatumWhere[Q psql.Filterable] struct {
Geospatial psql.WhereNullMod[Q, string]
Version psql.WhereMod[Q, int32]
OrganizationID psql.WhereMod[Q, int32]
H3cell psql.WhereNullMod[Q, string]
}
func (fieldseekerTrapdatumWhere[Q]) AliasedAs(alias string) fieldseekerTrapdatumWhere[Q] {
@ -1610,6 +1614,7 @@ func buildFieldseekerTrapdatumWhere[Q psql.Filterable](cols fieldseekerTrapdatum
Geospatial: psql.WhereNull[Q, string](cols.Geospatial),
Version: psql.Where[Q, int32](cols.Version),
OrganizationID: psql.Where[Q, int32](cols.OrganizationID),
H3cell: psql.WhereNull[Q, string](cols.H3cell),
}
}

View file

@ -140,6 +140,7 @@ type FieldseekerTreatment struct {
Geospatial null.Val[string] `db:"geospatial" `
Version int32 `db:"version,pk" `
OrganizationID int32 `db:"organization_id" `
H3cell null.Val[string] `db:"h3cell,generated" `
R fieldseekerTreatmentR `db:"-" `
}
@ -162,7 +163,7 @@ type fieldseekerTreatmentR struct {
func buildFieldseekerTreatmentColumns(alias string) fieldseekerTreatmentColumns {
return fieldseekerTreatmentColumns{
ColumnsExpr: expr.NewColumnsExpr(
"objectid", "activity", "treatarea", "areaunit", "product", "qty", "qtyunit", "method", "equiptype", "comments", "avetemp", "windspeed", "winddir", "raingauge", "startdatetime", "enddatetime", "insp_id", "reviewed", "reviewedby", "revieweddate", "locationname", "zone", "warningoverride", "recordstatus", "zone2", "treatacres", "tirecount", "cbcount", "containercount", "globalid", "treatmentlength", "treatmenthours", "treatmentlengthunits", "linelocid", "pointlocid", "polygonlocid", "srid", "sdid", "barrierrouteid", "ulvrouteid", "fieldtech", "ptaid", "flowrate", "habitat", "treathectares", "invloc", "temp_sitecond", "sitecond", "totalcostprodcut", "creationdate", "creator", "editdate", "editor", "targetspecies", "geometry", "geospatial", "version", "organization_id",
"objectid", "activity", "treatarea", "areaunit", "product", "qty", "qtyunit", "method", "equiptype", "comments", "avetemp", "windspeed", "winddir", "raingauge", "startdatetime", "enddatetime", "insp_id", "reviewed", "reviewedby", "revieweddate", "locationname", "zone", "warningoverride", "recordstatus", "zone2", "treatacres", "tirecount", "cbcount", "containercount", "globalid", "treatmentlength", "treatmenthours", "treatmentlengthunits", "linelocid", "pointlocid", "polygonlocid", "srid", "sdid", "barrierrouteid", "ulvrouteid", "fieldtech", "ptaid", "flowrate", "habitat", "treathectares", "invloc", "temp_sitecond", "sitecond", "totalcostprodcut", "creationdate", "creator", "editdate", "editor", "targetspecies", "geometry", "geospatial", "version", "organization_id", "h3cell",
).WithParent("fieldseeker.treatment"),
tableAlias: alias,
Objectid: psql.Quote(alias, "objectid"),
@ -223,6 +224,7 @@ func buildFieldseekerTreatmentColumns(alias string) fieldseekerTreatmentColumns
Geospatial: psql.Quote(alias, "geospatial"),
Version: psql.Quote(alias, "version"),
OrganizationID: psql.Quote(alias, "organization_id"),
H3cell: psql.Quote(alias, "h3cell"),
}
}
@ -287,6 +289,7 @@ type fieldseekerTreatmentColumns struct {
Geospatial psql.Expression
Version psql.Expression
OrganizationID psql.Expression
H3cell psql.Expression
}
func (c fieldseekerTreatmentColumns) Alias() string {
@ -1856,6 +1859,7 @@ type fieldseekerTreatmentWhere[Q psql.Filterable] struct {
Geospatial psql.WhereNullMod[Q, string]
Version psql.WhereMod[Q, int32]
OrganizationID psql.WhereMod[Q, int32]
H3cell psql.WhereNullMod[Q, string]
}
func (fieldseekerTreatmentWhere[Q]) AliasedAs(alias string) fieldseekerTreatmentWhere[Q] {
@ -1922,6 +1926,7 @@ func buildFieldseekerTreatmentWhere[Q psql.Filterable](cols fieldseekerTreatment
Geospatial: psql.WhereNull[Q, string](cols.Geospatial),
Version: psql.Where[Q, int32](cols.Version),
OrganizationID: psql.Where[Q, int32](cols.OrganizationID),
H3cell: psql.WhereNull[Q, string](cols.H3cell),
}
}

View file

@ -1,26 +0,0 @@
package main
import (
"encoding/json"
"errors"
//"fmt"
"github.com/stephenafamo/bob/types"
"github.com/uber/h3-go/v4"
)
func getPoint(geom types.JSON[json.RawMessage]) (h3.LatLng, error) {
/*
I need to figure out how to convert from the weird bob
type of types.JSON[json.RawMessage] to a X/Y coordinate to
here, but I need an Internet connection to do that effectively.
*/
return h3.LatLng{}, errors.New("need to implement this")
/*
msg, err := geom.Value()
if err != nil {
return h3.LatLng{}, fmt.Errorf("Can't get underlying JSON value: %w", err)
}
x := msg.Get("x")
y := msg.Get("y")
return h3.NewLatLng(x, y), nil
*/
}

2
go.mod
View file

@ -25,7 +25,7 @@ require (
github.com/stephenafamo/bob v0.42.0
github.com/stephenafamo/scan v0.7.0
github.com/tidwall/geojson v1.4.5
github.com/uber/h3-go/v4 v4.3.0
github.com/uber/h3-go/v4 v4.4.0
github.com/wasilibs/go-pgquery v0.0.0-20250409022910-10ac41983c07
golang.org/x/crypto v0.42.0
)

2
go.sum
View file

@ -224,6 +224,8 @@ github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+F
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
github.com/uber/h3-go/v4 v4.3.0 h1:5y5je8gu6+1pGzGo8soiudmgE3WJzfJRWdy0yhc3+HY=
github.com/uber/h3-go/v4 v4.3.0/go.mod h1:EyZ/EWguHlheIBcshTAMmQPYcaGKVvJ4qlzEHzC0BkU=
github.com/uber/h3-go/v4 v4.4.0 h1:sCHcZHvIKEbdt4rY5ZVs2HDNlCy2wXeJ98vAbz+iLok=
github.com/uber/h3-go/v4 v4.4.0/go.mod h1:c94kwXZNHVWkZGIN+y9dV81YVEttypqJpOjsmXGr68Y=
github.com/wasilibs/go-pgquery v0.0.0-20250409022910-10ac41983c07 h1:mJdDDPblDfPe7z7go8Dvv1AJQDI3eQ/5xith3q2mFlo=
github.com/wasilibs/go-pgquery v0.0.0-20250409022910-10ac41983c07/go.mod h1:Ak17IJ037caFp4jpCw/iQQ7/W74Sqpb1YuKJU6HTKfM=
github.com/wasilibs/wazero-helpers v0.0.0-20240620070341-3dff1577cd52 h1:OvLBa8SqJnZ6P+mjlzc2K7PM22rRUPE1x32G9DTPrC4=

7
h3.go
View file

@ -22,6 +22,13 @@ func h3ToBoundsGeoJSON(c h3.Cell) (string, error) {
}
*/
func toH3Cell(s string) (h3.Cell, error) {
c := h3.CellFromString(s)
if !c.IsValid() {
return c, fmt.Errorf("Invalid cell definition '%s'", s)
}
return c, nil
}
func h3ToGeoJSON(indexes []h3.Cell) (interface{}, error) {
featureCollection, err := geojson2h3.ToFeatureCollection(indexes)
if err != nil {

View file

@ -493,15 +493,20 @@ func htmlSource(w http.ResponseWriter, r *http.Request, user *models.User, id uu
return
}
treatment_models := modelTreatment(treatments)
latlng, err := s.H3Cell.LatLng()
if err != nil {
respondError(w, "Failed to get latlng", err, http.StatusInternalServerError)
return
}
data := ContentSource{
Inspections: inspections,
MapData: ComponentMap{
Center: s.LatLng,
Center: latlng,
//GeoJSON:
MapboxToken: MapboxToken,
Markers: []MapMarker{
MapMarker{
LatLng: s.LatLng,
LatLng: latlng,
},
},
Zoom: 13,

View file

@ -38,7 +38,7 @@ type BreedingSourceDetail struct {
Symbology string `json:"symbology"`
// Geographical Data
LatLng h3.LatLng `json:"latlng"`
H3Cell h3.Cell `json:"h3cell"`
Zone string `json:"zone"`
Zone2 string `json:"zone2"`
Jurisdiction string `json:"jurisdiction"`
@ -134,8 +134,7 @@ type TrapData struct {
Voltage float64 `json:"voltage"`
// Location Data
GeometryX float64 `json:"geometryX"`
GeometryY float64 `json:"geometryY"`
H3Cell h3.Cell `json:"h3cell"`
Zone string `json:"zone"`
Zone2 string `json:"zone2"`
@ -210,9 +209,12 @@ func toTemplateTraps(locations []sql.TrapLocationBySourceIDRow, trap_data []sql.
func toTemplateTrapData(trap_data models.FieldseekerTrapdatumSlice) ([]TrapData, error) {
var results []TrapData
for _, r := range trap_data {
geometry, err := getPoint(r.Geometry)
if r.H3cell.IsNull() {
continue
}
cell, err := toH3Cell(r.H3cell.MustGet())
if err != nil {
log.Error().Err(err).Msg("Failed to get geometry for trap data")
log.Error().Err(err).Msg("Failed to get location for trap data")
continue
}
results = append(results, TrapData{
@ -259,8 +261,7 @@ func toTemplateTrapData(trap_data models.FieldseekerTrapdatumSlice) ([]TrapData,
Voltage: r.Voltage.GetOr(0),
// Location Data
GeometryX: geometry.Lng,
GeometryY: geometry.Lat,
H3Cell: cell,
Zone: r.Zone.GetOr(""),
Zone2: r.Zone2.GetOr(""),
@ -331,9 +332,13 @@ func fsIntToBool(val null.Val[int16]) bool {
// toTemplateBreedingSource transforms the DB model into the display model
func toTemplateBreedingSource(source *models.FieldseekerPointlocation) *BreedingSourceDetail {
lat_lng, err := getPoint(source.Geometry)
if source.H3cell.IsNull() {
log.Error().Msg("h3 cell is null")
return nil
}
cell, err := toH3Cell(source.H3cell.MustGet())
if err != nil {
log.Error().Err(err).Msg("Failed to get point from point location")
log.Error().Err(err).Msg("Failed to get h3 cell from point location")
return nil
}
return &BreedingSourceDetail{
@ -361,7 +366,7 @@ func toTemplateBreedingSource(source *models.FieldseekerPointlocation) *Breeding
Symbology: source.Symbology.GetOr(""),
// Geographical Data
LatLng: lat_lng,
H3Cell: cell,
Zone: source.Zone.GetOr(""),
Zone2: source.Zone2.GetOr(""),
Jurisdiction: source.Jurisdiction.GetOr(""),