Commit ddf63ad0 by mushishixian

参数筛选

parent 893cdefc
......@@ -4,6 +4,7 @@ import (
"bom_server/cmd/queue"
"bom_server/configs"
"bom_server/internal/model"
"bom_server/internal/pkg/gredis"
"flag"
)
......@@ -13,5 +14,6 @@ func main() {
flag.Parse()
configs.Setup(path)
model.Setup()
gredis.Setup()
queue.Sync()
}
......@@ -14,16 +14,16 @@ type RecvPro struct {
}
func init() {
//queueExchange := rabbitmq.QueueExchange{
// "bom_match",
// "bom_match",
// "bom",
// "direct",
// "amqp://huntadmin:jy2y2900@192.168.1.237:5672/",
//}
//
//str := `{"bom_id":237,"delivery_type":1,"sort":2}`
//rabbitmq.Send(queueExchange, str)
queueExchange := rabbitmq.QueueExchange{
"bom_match",
"bom_match",
"bom",
"direct",
"amqp://huntadmin:jy2y2900@192.168.1.237:5672/",
}
str := `{"bom_id":369,"delivery_type":1,"sort":1}`
rabbitmq.Send(queueExchange, str)
}
func (t *RecvPro) Consumer(dataByte []byte) (err error) {
......
......@@ -24,11 +24,13 @@ type Database struct {
}
type Redis struct {
Host string `ini:"host"`
Password string `ini:"password"`
MaxIdle int `ini:"max_idle"`
MaxActive int `ini:"max_active"`
IdleTimeout time.Duration `ini:"idle_timeout"`
WriteHost string `ini:"write_host"`
ReadHost string `ini:"read_host"`
WritePassword string `ini:"write_password"`
ReadPassword string `ini:"read_password"`
MaxIdle int `ini:"max_idle"`
MaxActive int `ini:"max_active"`
IdleTimeout time.Duration `ini:"idle_timeout"`
}
type ES struct {
......
......@@ -7,7 +7,7 @@ require (
github.com/gin-gonic/gin v1.6.3
github.com/go-ini/ini v1.56.0
github.com/go-kratos/kratos v0.5.0
github.com/go-sql-driver/mysql v1.5.0
github.com/gomodule/redigo v2.0.0+incompatible
github.com/ichunt2019/go-rabbitmq v1.0.1
github.com/imroc/req v0.3.0
github.com/jinzhu/gorm v1.9.12
......
......@@ -129,6 +129,9 @@ github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0=
github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
github.com/gomodule/redigo/redis v0.0.0-do-not-use h1:J7XIp6Kau0WoyT4JtXHT3Ei0gA1KkSc6bc87j9v9WIo=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
......
......@@ -130,3 +130,25 @@ func Assert(input interface{}, needType string) (result interface{}) {
}
return
}
func ToString(a interface{}) string {
if v, p := a.(int); p {
return strconv.Itoa(v)
}
if v, p := a.(int16); p {
return strconv.Itoa(int(v))
}
if v, p := a.(int32); p {
return strconv.Itoa(int(v))
}
if v, p := a.(uint); p {
return strconv.Itoa(int(v))
}
if v, p := a.(float32); p {
return strconv.FormatFloat(float64(v), 'f', -1, 32)
}
if v, p := a.(float64); p {
return strconv.FormatFloat(v, 'f', -1, 32)
}
return "change to String error"
}
package logic
import (
"bom_server/configs"
"bom_server/internal/common"
"bom_server/internal/mapping"
"bom_server/internal/model"
"bom_server/internal/pkg/gredis"
"context"
"fmt"
"github.com/gomodule/redigo/redis"
"github.com/tidwall/gjson"
es "gopkg.in/olivere/elastic.v5"
"regexp"
"strconv"
"strings"
)
//根据参数去匹配商品
func MatchGoodsNameByAttrs(bomItems []model.BomItem) (result []model.BomItem, err error) {
fmt.Println("开始匹配参数")
client, err := es.NewClient(es.SetURL(configs.ESSetting.Url))
if err != nil {
return
}
defer client.Stop()
search := client.MultiSearch().Index("goods_map_test")
//先根据参数去构建批量查询条件
for _, item := range bomItems {
if item.GoodsName == "" && item.Attrs != "" {
//先去切割参数得到参数列表
attrs := splitAttrs(item.Attrs)
var attrsSlice []string
//去转换每一个参数,得到去查询es的标准格式
for _, attr := range attrs {
attr = TransformESParam(attr)
attrsSlice = append(attrsSlice, attr)
}
query := getQuery(attrsSlice)
source := es.NewSearchSource().Query(query)
source = source.From(0).Size(1)
searchRequest := es.NewSearchRequest().Source(source)
search.Add(searchRequest)
}
}
res, err := search.Do(context.Background())
if err != nil {
return
}
if len(res.Responses) == 0 {
return
}
//因为是多重查询,所以会有多套结果
for key, responses := range res.Responses {
//有数据进行转换
if responses.Hits != nil {
for _, hit := range responses.Hits.Hits {
res, _ := hit.Source.MarshalJSON()
bomItems[key].GoodsName = gjson.Get(string(res), "goods_name").String()
}
}
}
return
}
//切割参数
func splitAttrs(attrs string) (result []string) {
result = strings.Split(attrs, " ")
if len(result) > 1 {
return
}
result = strings.Split(attrs, ",")
if len(result) > 1 {
return
}
result = strings.Split(attrs, "|")
if len(result) > 1 {
return
}
result = strings.Split(attrs, ",")
if len(result) > 1 {
return
}
return
}
//将写法转成正规写法,转换单位,比如有的人喜欢将Ω输成欧姆或者O,所以要统一转成正常的Ω
func changeKeyword(attr string) (result string) {
regulars := mapping.KeywordRegular
for regexpStr, regular := range regulars {
compile, _ := regexp.Compile(regexpStr)
attr = compile.ReplaceAllString(attr, regular)
}
return attr
}
//将属性值转成ES的标准值(例如 : 阻值(欧姆)€3000)
func TransformESParam(attr string) (result string) {
attr = changeKeyword(attr)
unitMapping := mapping.UnitValueMapping
//获取该属性对应的单位
for unit, _ := range unitMapping {
//todo 先去截取属性,得到参数,比如3kΩ(3001)这种形式的参数,要截取成3kΩ
index := strings.Index(attr, unit)
if index > 0 {
attr = string([]rune(attr)[:index+len(unit)-1])
}
//得到截取后的参数,去得到需要用于es查询的参数
attrValue := getAttrValueByAttr(attr)
return attrValue
}
return
}
//根据参数单位或者参数值获取对应的重要属性,组成最后查询的字符串
//±
func getAttrValueByAttr(attr string) (attrValue string) {
//先找出单位
r, _ := regexp.Compile(`[\d.]|±|\+_|\+-|/|\(.*\)|`)
attrUnit := r.ReplaceAllString(attr, "")
//如果单位是W,则要进行除法计算
if strings.ToUpper(attrUnit) == "W" {
//提取值,进行计算
attr = strings.TrimRight(attr, "W")
attr = strings.TrimRight(attr, "w")
attrSlice := strings.Split(attr, "/")
if len(attrSlice) == 2 {
var res float64
a, _ := strconv.ParseFloat(attrSlice[0], 64)
b, _ := strconv.ParseFloat(attrSlice[1], 64)
res = a / b
attr = fmt.Sprintf("%.3f", res) + "W"
}
}
//再找出纯数字
var attrNumber float64
numberR, _ := regexp.Compile(`(\d+(\.\d+)?)`)
pureNumber := numberR.FindString(attr)
attrNumber, _ = strconv.ParseFloat(pureNumber, 64)
//找出对应单位需要转换的值
var attrName string
if attrUnit != "" {
for unit, value := range mapping.UnitValueMapping {
//如果不是标准最小单位,则要进行转换
if attrUnit == unit {
value64, _ := strconv.ParseFloat(value, 64)
//还要找到对应的属性,先找到基础单位
var baseUnit string
if value, exist := mapping.UnitBaseMapping[attrUnit]; exist {
baseUnit = value
}
if baseUnit == "" {
return attr
}
//获取重要属性名称
if value, exist := mapping.UnitAttrMapping[baseUnit]; exist {
attrName = value
}
attrNumberStr := common.ToString(attrNumber * value64)
attrValue = attrName + "€" + attrNumberStr
break
}
}
} else {
//再去找没有单位的对应属性
attrName, _ = redis.String(gredis.HGet("sku_map2", attr))
if attrName != "" {
attrValue = attrName + "€" + attr
} else {
attrValue = attr
}
}
return attrValue
}
//获取匹配的条件
func getQuery(attrs []string) (query *es.BoolQuery) {
subQuery := es.NewBoolQuery()
for _, attr := range attrs {
subQuery = subQuery.Should(es.NewTermQuery("attrs.attr_value", attr))
}
nestedQuery := es.NewNestedQuery("attrs", subQuery)
query = es.NewBoolQuery()
query = query.Filter(nestedQuery)
return query
}
......@@ -7,6 +7,7 @@ import (
"context"
"encoding/json"
"errors"
"fmt"
"math"
"regexp"
"strings"
......@@ -32,7 +33,7 @@ func MatchGoods(message model.BomMessage) (err error) {
}
bomItems := bom.BomItems
perGoDealNumber := 40
//开启协程处理搜索.每50个开启一个协程
//开启协程处理搜索
var wg sync.WaitGroup
//判断是否有余数
extraNumber := len(bomItems) % perGoDealNumber
......@@ -76,6 +77,13 @@ func SearchGoods(bomId int, bomItems []model.BomItem, deliveryType, sort int, wg
panic(err)
}
defer client.Stop()
//匹配之前,去遍历bom_item,把没有型号名称但是有参数的bom_item进行型号补充
MatchGoodsNameByAttrs(bomItems)
//bomItems, err = MatchGoodsNameByAttrs(bomItems)
//if err != nil {
// return err
//}
//第一次先去精确匹配
goodsMapList, err := getUpdateGoodsData(bomId, bomItems, deliveryType, sort, client, true)
if err != nil {
......@@ -178,7 +186,10 @@ func getUpdateGoodsData(bomId int, bomItems []model.BomItem, deliveryType, sort
index = index + ",zhuanmai"
//查完以后去除已经匹配的自营商品,然后去搜索联营的商品
bomItems = removeZiyingMatchBomItem(ziyingGoodsMapList, bomItems)
lianyingGoodsMapList, _ := search(index, bomId, bomItems, deliveryType, sort, client, rawSearch)
var lianyingGoodsMapList []GoodsMap
if len(bomItems) != 0 {
lianyingGoodsMapList, _ = search(index, bomId, bomItems, deliveryType, sort, client, rawSearch)
}
goodsMapList = append(ziyingGoodsMapList, lianyingGoodsMapList...)
} else {
index = index + ",zhuanmai,liexin_ziying"
......@@ -215,6 +226,7 @@ func search(index string, bomId int, bomItems []model.BomItem, deliveryType, sor
if !rawSearch {
bom.GoodsName = common.SubKeyWordStr(bom.GoodsName)
if bom.GoodsName == "" {
fmt.Println("continue")
continue
}
}
......@@ -222,6 +234,7 @@ func search(index string, bomId int, bomItems []model.BomItem, deliveryType, sor
searchRequest := getSearchParams(index, bom.GoodsName, bom.BrandName, sort, bom.Number, rawSearch)
search.Add(searchRequest)
}
//:todo 这里有bug
res, err := search.Do(context.Background())
if err != nil {
return
......
package mapping
var KeywordRegular = map[string]string{
//`^(.* )?([\d\.]+)(欧|欧姆|R|r)( .*)?$`: `$1$2Ω$4`,
//`^(.* )?([\d\.]+)(U|u|μ)(.?)( .*)?$`: `$1$2Μ$4$5`,
"COG": "C0G",
"NPO": "NP0",
"(欧姆|欧|O|o|R|r)": "Ω",
"华科|华新科技|华新科": "华新",
"U|u|μ": "M",
}
......@@ -2,22 +2,67 @@ package mapping
//属性单位对应属性
var UnitAttrMapping = map[string]string{
"r ": "阻值(欧姆)",
": "阻值(欧姆)",
"r": "阻值(欧姆)",
": "阻值(欧姆)",
"mh": "电感",
"w": "功率",
"W": "功率",
"Ω/r ": "内阻",
"% ": "精度",
"%": "精度",
}
//封装列表
var PackingList = []string{
"0402",
"0603",
//属性对应的基础属性
var UnitBaseMapping = map[string]string{
"μΩ": "Ω",
"mΩ": "Ω",
"Ω": "Ω",
"kΩ": "Ω",
"KΩ": "Ω",
"MΩ": "Ω",
"pF": "F",
"nF": "F",
"μF": "F",
"mF": "F",
"F": "F",
"μH": "H",
"mH": "H",
"H": "H",
"V": "V",
"kV": "V",
"mA": "A",
"A": "A",
"W": "W",
"kW": "W",
"KW": "W",
"%": "%",
}
//介质列表
var MediaList = []string{
"X5U",
"X7R",
//根据单位对值的转换,比如1kΩ=>1000Ω
var UnitValueMapping = map[string]string{
"μΩ": "0.000001",
"mΩ": "0.001",
"Ω": "1",
"kΩ": "1000",
"KΩ": "1000",
"MΩ": "1000000",
"pF": "1",
"nF": "1000",
"μF": "1000000",
"mF": "1000000000",
"F": "1000000000000",
"μH": "1",
"mH": "1000",
"H": "1000000",
"V": "1",
"kV": "1000",
"mA": "1",
"A": "1000",
"W": "1",
"kW": "1000",
"%": "0.01",
}
package mapping
//封装列表
var PackingList = []string{
"0402",
"0603",
}
//介质列表
var MediaList = []string{
"X5U",
"X7R",
}
package gredis
import (
"bom_server/configs"
"encoding/json"
"github.com/gomodule/redigo/redis"
"time"
)
var writeConn, readConn *redis.Pool
func Setup() (err error) {
writeHost := configs.RedisSetting.WriteHost
readHost := configs.RedisSetting.ReadHost
writePassword := configs.RedisSetting.WritePassword
readPassword := configs.RedisSetting.ReadPassword
writeConn, err = getConn(writeHost, writePassword)
if err != nil {
return
}
readConn, err = getConn(readHost, readPassword)
if err != nil {
return
}
return nil
}
func getConn(writeHost, password string) (pool *redis.Pool, err error) {
maxIdle := configs.RedisSetting.MaxIdle
maxActive := configs.RedisSetting.MaxActive
pool = &redis.Pool{
MaxIdle: maxIdle,
MaxActive: maxActive,
Dial: func() (redis.Conn, error) {
c, err := redis.Dial("tcp", writeHost)
if err != nil {
return nil, err
}
if password != "" {
if _, err := c.Do("AUTH", password); err != nil {
c.Close()
return nil, err
}
}
return c, err
},
TestOnBorrow: func(c redis.Conn, t time.Time) error {
_, err := c.Do("PING")
return err
},
}
return
}
//最基础的键值操作
func Set(key string, data interface{}) error {
conn := writeConn.Get()
defer conn.Close()
value, err := json.Marshal(data)
if err != nil {
return err
}
_, err = conn.Do("SET", key, value)
if err != nil {
return err
}
return nil
}
func Exists(key string) bool {
conn := readConn.Get()
defer conn.Close()
exists, err := redis.Bool(conn.Do("EXISTS", key))
if err != nil {
return false
}
return exists
}
func Get(key string) (interface{}, error) {
conn := readConn.Get()
defer conn.Close()
reply, err := conn.Do("GET", key)
if err != nil {
return nil, err
}
return reply, nil
}
func Delete(key string) (bool, error) {
conn := writeConn.Get()
defer conn.Close()
return redis.Bool(conn.Do("DEL", key))
}
//哈希操作
func HSet(key string, k interface{}, data interface{}) error {
conn := writeConn.Get()
defer conn.Close()
value, err := json.Marshal(data)
if err != nil {
return err
}
_, err = conn.Do("HSET", key, k, value)
if err != nil {
return err
}
return nil
}
func HGet(key string, k interface{}) (interface{}, error) {
conn := readConn.Get()
defer conn.Close()
reply, err := conn.Do("HGET", key, k)
if err != nil {
return nil, err
}
return reply, nil
}
func HDelete(key string, k interface{}) (bool, error) {
conn := writeConn.Get()
defer conn.Close()
return redis.Bool(conn.Do("HDEL", key, k))
}
package main
import (
"fmt"
"github.com/shopspring/decimal"
)
type abc struct {
Goods_id float64 `json:"goods_id"`
Goods_name string `json:"goods_name"`
}
import "bom_server/internal/logic"
func main() {
//a := `{"goods_id":1.1572417766286e+18,"goods_name":"LM358"}`
//
//aaa := &abc{}
//err := json.Unmarshal([]byte(a),aaa)
//
//if err !=nil{
// fmt.Println(err)
//}
//
//fmt.Println(aaa)
//
//d := json.NewDecoder(bytes.NewReader([]byte(a)))
//d.UseNumber()
//err = d.Decode(&aaa)
//if err != nil {
// // 错误处理
//}
//fmt.Println(aaa)
//fmt.Printf("%f\n", aaa.Goods_id)
numStr := 1.1572417766286e+18
decimalNum := decimal.NewFromFloat(numStr)
//if err != nil {
// return
//}
fmt.Println(decimalNum.String())
logic.ChangeUnit("100kr(1002) ")
//logic.ChangeUnit("10KΩ(1002) ")
//logic.ChangeUnit("±1%")
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment