text search
This commit is contained in:
27
utils/geo.go
27
utils/geo.go
@@ -83,6 +83,7 @@ func SearchTokens(label string) []string {
|
||||
var tokens []string
|
||||
seen := make(map[string]bool)
|
||||
kept := 0 // multi-character tokens so far: a lone letter needs one
|
||||
var filler []string // packaging words, kept only if nothing else survives
|
||||
for _, raw := range strings.FieldsFunc(strings.ToLower(label), func(r rune) bool {
|
||||
return !(r >= 'a' && r <= 'z' || r >= '0' && r <= '9')
|
||||
}) {
|
||||
@@ -92,15 +93,39 @@ func SearchTokens(label string) []string {
|
||||
if len(raw) < 2 && (kept == 0 || isMultiplier(raw)) {
|
||||
continue
|
||||
}
|
||||
seen[raw] = true
|
||||
if isPackaging(raw) {
|
||||
filler = append(filler, raw)
|
||||
continue
|
||||
}
|
||||
if len(raw) > 1 {
|
||||
kept++
|
||||
}
|
||||
seen[raw] = true
|
||||
tokens = append(tokens, raw)
|
||||
}
|
||||
// "Dettol bottle pack" is a scan of Dettol. Only when the label is nothing
|
||||
// but packaging does that packaging become the search.
|
||||
if len(tokens) == 0 {
|
||||
return filler
|
||||
}
|
||||
return tokens
|
||||
}
|
||||
|
||||
// isPackaging is what the label says about the wrapper rather than the
|
||||
// product: "Dettol bottle pack", "Parle G biscuit pack". Lens reads these off
|
||||
// the packet and no catalogue name carries them, so every one of them used to
|
||||
// be a word the row had to contain — and "Dettol bottle pack" found no Dettol
|
||||
// at all. Treated like pack sizes: real words, just not the product's name.
|
||||
func isPackaging(tok string) bool {
|
||||
switch tok {
|
||||
case "pack", "packs", "packet", "packets", "bottle", "bottles",
|
||||
"box", "boxes", "jar", "jars", "tin", "tins", "pouch", "pouches",
|
||||
"carton", "cartons", "sachet", "sachets", "combo", "refill":
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// isMultiplier is the "x" of "2 x 50gm" and the "n" of a multipack — a single
|
||||
// character that joins sizes rather than naming a product.
|
||||
func isMultiplier(tok string) bool {
|
||||
|
||||
@@ -102,3 +102,29 @@ func TestFoldAndTightenSeparators(t *testing.T) {
|
||||
t.Fatalf("tighten: got %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
// Lens reads the wrapper as well as the product. No catalogue name carries
|
||||
// "bottle" or "pack", so requiring them found no Dettol at all.
|
||||
func TestSearchTokensDropsPackagingWords(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
label string
|
||||
want []string
|
||||
}{
|
||||
{"Dettol bottle pack", []string{"dettol"}},
|
||||
{"Parle G biscuit pack", []string{"parle", "g", "biscuit"}},
|
||||
{"Milk Bikis pack", []string{"milk", "bikis"}},
|
||||
{"Nescafe jar 50g", []string{"nescafe"}},
|
||||
{"pack", []string{"pack"}}, // nothing else: the wrapper is the search
|
||||
{"combo pack", []string{"combo", "pack"}}, // ditto, both kept
|
||||
} {
|
||||
got := SearchTokens(tc.label)
|
||||
if len(got) != len(tc.want) {
|
||||
t.Fatalf("%q: got %v want %v", tc.label, got, tc.want)
|
||||
}
|
||||
for i := range tc.want {
|
||||
if got[i] != tc.want[i] {
|
||||
t.Fatalf("%q: got %v want %v", tc.label, got, tc.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user