nutrition field
This commit is contained in:
@@ -64,6 +64,17 @@ var scalarFacts = []string{
|
||||
|
||||
var arrayFacts = []string{"providers", "highlights", "nutrients"}
|
||||
|
||||
// The structured nutrition panel: a jsonb column the agent team fills, which
|
||||
// the customer app renders. Its own category because it is neither a scalar
|
||||
// nor a text[] — stored as a string it would reach the app as an escaped blob
|
||||
// inside the snapshot instead of an object, and every reader would have to
|
||||
// decode it twice.
|
||||
//
|
||||
// Absent on every brand table today, which costs this fact and nothing else.
|
||||
// The lines in `nutrients` above are parsed into a panel at read time, so a
|
||||
// product backfilled before the column exists still shows figures.
|
||||
var jsonFacts = []string{"nutrition"}
|
||||
|
||||
type product struct {
|
||||
Productid int
|
||||
Productbrand string
|
||||
@@ -312,7 +323,7 @@ func factColumnsOf(db *gorm.DB, table string) []string {
|
||||
}
|
||||
|
||||
var keep []string
|
||||
for _, c := range append(append([]string{}, scalarFacts...), arrayFacts...) {
|
||||
for _, c := range append(append(append([]string{}, scalarFacts...), arrayFacts...), jsonFacts...) {
|
||||
if present[c] {
|
||||
keep = append(keep, c)
|
||||
}
|
||||
@@ -332,7 +343,9 @@ func factsFor(db *gorm.DB, table string, cols []string, imageID string) (map[str
|
||||
|
||||
selects := make([]string, 0, len(cols))
|
||||
for _, c := range cols {
|
||||
if isArrayFact(c) {
|
||||
// jsonb and text[] are both cast to text for the same reason: GORM's
|
||||
// raw scan cannot land either one in a Go value directly.
|
||||
if isArrayFact(c) || isJSONFact(c) {
|
||||
selects = append(selects, c+"::text AS "+c)
|
||||
continue
|
||||
}
|
||||
@@ -356,6 +369,21 @@ func factsFor(db *gorm.DB, table string, cols []string, imageID string) (map[str
|
||||
if text == "" {
|
||||
continue
|
||||
}
|
||||
if isJSONFact(c) {
|
||||
// Embedded as an object, not as the text the column scanned to.
|
||||
// Stored as a string it would reach the app as an escaped blob
|
||||
// inside the snapshot, and every reader would decode it twice.
|
||||
//
|
||||
// Unreadable JSON is skipped rather than stored: an absent panel
|
||||
// falls back to the nutrient lines at read time, a broken one does
|
||||
// not.
|
||||
var panel models.NutritionPanel
|
||||
if err := json.Unmarshal([]byte(text), &panel); err != nil || !panel.HasValues() {
|
||||
continue
|
||||
}
|
||||
facts[c] = panel
|
||||
continue
|
||||
}
|
||||
if isArrayFact(c) {
|
||||
values := models.ParsePGArray(text)
|
||||
kept := make([]string, 0, len(values))
|
||||
@@ -374,6 +402,15 @@ func factsFor(db *gorm.DB, table string, cols []string, imageID string) (map[str
|
||||
return facts, true
|
||||
}
|
||||
|
||||
func isJSONFact(name string) bool {
|
||||
for _, c := range jsonFacts {
|
||||
if c == name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isArrayFact(name string) bool {
|
||||
for _, c := range arrayFacts {
|
||||
if c == name {
|
||||
|
||||
Reference in New Issue
Block a user