fix: match padded stock names in security searches

This commit is contained in:
2026-10-09 22:56:22 +08:00
parent d39fb0e0d2
commit 1496d77bcc
4 changed files with 27 additions and 2 deletions
+16
View File
@@ -47,6 +47,22 @@ func testScreeningLifecycle(t *testing.T, ctx context.Context, pool *pgxpool.Poo
if err := repository.NewMarketRepository(pool).Save(ctx, provider, []model.Instrument{instrument}, time.Now().UTC(), ""); err != nil {
t.Fatal(err)
}
searchRepo := repository.NewMarketRepository(pool)
if err := searchRepo.Save(ctx, provider, []model.Instrument{{Symbol: "002215", Exchange: "SZSE", Name: "诺 普 信", PriceCents: 1000, ObservedAt: observed}}, time.Now().UTC(), ""); err != nil {
t.Fatal(err)
}
for _, query := range []string{"诺普信", "诺 普 信", " 诺\t普 信 ", "002215", "002 215"} {
stocks, err := searchRepo.List(ctx, query)
if err != nil || len(stocks) != 1 || stocks[0].Symbol != "002215" || stocks[0].Name != "诺 普 信" {
t.Fatalf("padded security search %q: %v, %v", query, stocks, err)
}
}
for _, query := range []string{"not-a-security", "%", "_"} {
stocks, err := searchRepo.List(ctx, query)
if err != nil || len(stocks) != 0 {
t.Fatalf("literal security search %q matched: %v, %v", query, stocks, err)
}
}
repo := repository.NewScreeningRepository(pool)
targets, err := repo.Targets(ctx, provider)
if err != nil || len(targets) != 1 {
+5 -1
View File
@@ -7,6 +7,7 @@ import (
"git.sundynix.cn/Blizzard/Veyra/internal/model"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgxpool"
"strings"
"time"
)
@@ -14,7 +15,10 @@ type MarketRepository struct{ pool *pgxpool.Pool }
func NewMarketRepository(pool *pgxpool.Pool) *MarketRepository { return &MarketRepository{pool} }
func (r *MarketRepository) List(ctx context.Context, query string) ([]model.Instrument, error) {
rows, e := r.pool.Query(ctx, `SELECT id,symbol,exchange,name,price_cents,observed_at,received_at,source_id,source_version FROM veyra_instrument WHERE symbol LIKE $1 OR name LIKE $1 ORDER BY (price_cents>0) DESC,symbol LIMIT 100`, "%"+query+"%")
// Vendors pad some short names with whitespace (for example "诺 普 信").
// Normalize only for matching; preserve the supplied name in stored data.
pattern := "%" + strings.NewReplacer(`\`, `\\`, "%", `\%`, "_", `\_`).Replace(query) + "%"
rows, e := r.pool.Query(ctx, `SELECT id,symbol,exchange,name,price_cents,observed_at,received_at,source_id,source_version FROM veyra_instrument WHERE symbol LIKE regexp_replace($1,'[[:space:] ]+','','g') OR regexp_replace(name,'[[:space:] ]+','','g') LIKE regexp_replace($1,'[[:space:] ]+','','g') ORDER BY (price_cents>0) DESC,symbol LIMIT 100`, pattern)
if e != nil {
return nil, mapError(e)
}