Commit 9d4889cb by mushishixian

temp

parent 8f487d98
......@@ -14,17 +14,17 @@ 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":666,"delivery_type":1,"sort":1}`
//str := `{"bom_id":717,"delivery_type":1,"sort":1}`
//rabbitmq.Send(queueExchange, str)
queueExchange := rabbitmq.QueueExchange{
"bom_match",
"bom_match",
"bom",
"direct",
"amqp://huntadmin:jy2y2900@192.168.1.237:5672/",
}
//str := `{"bom_id":666,"delivery_type":1,"sort":1}`
str := `{"bom_id":692,"delivery_type":1,"sort":1}`
rabbitmq.Send(queueExchange, str)
}
func (t *RecvPro) Consumer(dataByte []byte) (err error) {
......
......@@ -89,10 +89,9 @@ func UpdateBomItem(bomId, bomItemId int) (err error) {
return err
}
defer client.Stop()
//先去查询品牌映射,有映射关系的,就用映射关系得到的brand_id进行查询
bomItems, err = GetBrandMap(bomItems)
//匹配之前,去遍历bom_item,把没有型号名称但是有参数的bom_item进行型号补充
bomItems, err = MatchGoodsNameByAttrs(bomItems)
//bomItems, err = MatchGoodsNameByAttrs(bomItems)
//第一次去精确匹配,没有再去模糊匹配
var goodsMapList []GoodsMap
goodsMapList, err = getUpdateGoodsData(bomId, bomItems, where.DeliveryType, where.Sort, client, true)
......
package logic
import (
"bom_server/configs"
"bom_server/internal/model"
"context"
"github.com/tidwall/gjson"
es "gopkg.in/olivere/elastic.v5"
"regexp"
"strings"
)
//和品牌映射有关的逻辑
func GetBrandMap(bomItems []model.BomItem) (result []model.BomItem, err error) {
client, err := es.NewClient(es.SetURL(configs.ESSetting.Url))
if err != nil {
return
}
index := "stand_brand"
search := client.MultiSearch().Index(index)
for _, bomItem := range bomItems {
search = searchBrandMap(bomItem, search)
}
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 {
var lyBrandIds []string
for _, hit := range responses.Hits.Hits {
res, _ := hit.Source.MarshalJSON()
lyIdArray := gjson.Get(string(res), "attrs.#.attr_brand_id").Array()
for _, id := range lyIdArray {
idSlice := strings.Split(id.String(), ",")
lyBrandIds = append(lyBrandIds, idSlice...)
}
bomItems[key].ZyBrandId = hit.Id
bomItems[key].ZyBrandName = gjson.Get(string(res), "stand_zy_brand_name").String()
}
bomItems[key].LyBrandIds = lyBrandIds
}
}
result = bomItems
return
}
//根据用户输入的品牌获取映射后的品牌,没有映射的话不变,有的话变
func searchBrandMap(bomItem model.BomItem, search *es.MultiSearchService) (result *es.MultiSearchService) {
query := getBrandMapQuery(bomItem)
source := es.NewSearchSource().Query(query)
source = source.From(0).Size(1)
searchRequest := es.NewSearchRequest().Source(source)
search.Add(searchRequest)
return search
}
//获取品牌映射搜索的查询条件
func getBrandMapQuery(bomItem model.BomItem) (query *es.BoolQuery) {
var subQuery *es.TermQuery
var nestedQuery *es.NestedQuery
query = es.NewBoolQuery()
brandName := bomItem.BrandName
brandName = strings.ToUpper(brandName)
//提取出纯中文
r, _ := regexp.Compile("[\u4e00-\u9fa5]+")
brandNameCn := r.FindString(brandName)
if brandNameCn != "" {
query.Should(es.NewMatchQuery("brand_name_cn", brandNameCn))
}
//提取出纯英文
re, _ := regexp.Compile("[A-Za-z0-9]+")
brandNameEn := re.FindString(brandName)
subQuery = es.NewTermQuery("attrs.attr_brand_name", brandNameEn)
nestedQuery = es.NewNestedQuery("attrs", subQuery)
query.Should(nestedQuery)
query.MinimumNumberShouldMatch(1)
return query
}
//
package logic
import (
"bom_server/internal/mapping"
"bom_server/internal/pkg/gredis"
"github.com/gomodule/redigo/redis"
"regexp"
)
//转换封装
func TransformEncap(encap string) (attrValue string) {
numberR, _ := regexp.Compile(mapping.PureNumberRegular)
pureNumber := numberR.FindString(encap)
//判断是多少位数字,如果是3位,则代表可能需要往前面补零
if len(pureNumber) == 3 {
encapCheck := "0" + pureNumber
//补全完以后,去sku_map2尝试获取值,如果存在的话,就代表是正确的封装
attrName, _ := redis.String(gredis.HGet("sku_map2", encapCheck))
if attrName != "" {
pureNumber = encapCheck
}
}
//再去找对应属性
attrValue = "封装" + "€" + pureNumber
return attrValue
}
......@@ -4,11 +4,7 @@ import (
"bom_server/configs"
"bom_server/internal/common"
"bom_server/internal/model"
"context"
"encoding/json"
"math"
"regexp"
"strings"
"sync"
"github.com/prometheus/common/log"
......@@ -21,7 +17,6 @@ import (
3.搜索匹配到以后,用goods_id去请求商品服务
4.得到具体的商品数据以后,针对对应的商品进行修改
**/
func MatchGoods(message model.BomMessage) (err error) {
//获取bom
bomId := message.BomId
......@@ -30,6 +25,7 @@ func MatchGoods(message model.BomMessage) (err error) {
return nil
}
bomItems := bom.BomItems
//每个协程处理的数量
var perGoDealNumber int
if configs.ApiSetting.Mode == "debug" {
perGoDealNumber = 200
......@@ -57,9 +53,11 @@ func MatchGoods(message model.BomMessage) (err error) {
bomData = bomItems[i : i+perGoDealNumber]
}
go func() {
if len(bomData) != 0 {
if err := SearchGoods(bomId, bomData, message.DeliveryType, message.Sort, &wg); err != nil {
log.Error(err)
}
}
}()
}
wg.Wait()
......@@ -69,32 +67,29 @@ func MatchGoods(message model.BomMessage) (err error) {
//去es搜索商品,得到对应的商品对应关系
func SearchGoods(bomId int, bomItems []model.BomItem, deliveryType, sort int, wg *sync.WaitGroup) (err error) {
client, err := es.NewClient(es.SetURL(configs.ESSetting.Url))
if err != nil {
panic(err)
}
defer func() {
wg.Done()
client.Stop()
}()
if len(bomItems) == 0 {
return
}
//去除首尾空格
bomItems = common.TrimBomItemSpace(bomItems)
client, err := es.NewClient(es.SetURL(configs.ESSetting.Url))
if err != nil {
panic(err)
}
defer client.Stop()
//先去查询品牌映射,有映射关系的,就用映射关系得到的brand_id进行查询
bomItems, err = GetBrandMap(bomItems)
//匹配之前,去遍历bom_item,把没有型号名称但是有参数的bom_item进行型号补充
bomItems, err = MatchGoodsNameByAttrs(bomItems)
//获取转换后的标准参数,或者是识别出参数列是否有型号
bomItems = GetStandardAttrs(bomItems)
//第一次先去精确匹配
goodsMapList, err := getUpdateGoodsData(bomId, bomItems, deliveryType, sort, client, true)
if err != nil {
return
}
//要删除已经精确匹配过的bomItem
//要删除已经精确匹配过的bomItem,得到需要去模糊匹配的商品
var fuzzyBomItems []model.BomItem
for _, bomItem := range bomItems {
if !checkInGoodsMap(bomItem, goodsMapList) {
//不在精确匹配结果里面的,同时商品名称不能为空的
if !checkInGoodsMap(bomItem, goodsMapList) && bomItem.GoodsName != "" {
fuzzyBomItems = append(fuzzyBomItems, bomItem)
}
}
......@@ -177,190 +172,13 @@ func getUpdateGoodsData(bomId int, bomItems []model.BomItem, deliveryType, sort
return
}
index := configs.ESSetting.GoodsIndexName
var ziyingGoodsMapList []GoodsMap
//如果是大陆收货(type=1),就要包含专卖,其中自营单独查
if deliveryType == 1 {
//如果是综合排序(sort=1)
if sort == 1 {
//先去自营查一遍
ziyingGoodsMapList, err = search("liexin_ziying", bomId, bomItems, deliveryType, sort, client, rawSearch)
if err != nil {
return nil, err
}
index = index + ",zhuanmai"
//查完以后去除已经匹配的自营商品,然后去搜索联营的商品
bomItems = removeZiyingMatchBomItem(ziyingGoodsMapList, bomItems)
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"
goodsMapList, err = search(index, bomId, bomItems, deliveryType, sort, client, rawSearch)
if err != nil {
return nil, err
}
}
} else {
index = index + ",zhuanmai,liexin_ziying"
goodsMapList, err = search(index, bomId, bomItems, deliveryType, sort, client, rawSearch)
if err != nil {
return nil, err
}
}
return
}
func removeZiyingMatchBomItem(ziyingGoodsMapList []GoodsMap, bomItems []model.BomItem) (result []model.BomItem) {
for _, bomItem := range bomItems {
if !checkInGoodsMap(bomItem, ziyingGoodsMapList) {
result = append(result, bomItem)
}
}
return
}
func search(index string, bomId int, bomItems []model.BomItem, deliveryType, sort int, client *es.Client, rawSearch bool) (goodsMapList []GoodsMap, err error) {
//先去自营查一遍
search := client.MultiSearch().Index(index)
searchFlag := false
//多重搜索,第一次先去精确匹配
for _, bom := range bomItems {
//如果是模糊查询,还要去截取字符串
if !rawSearch {
bom.GoodsName = common.SubKeyWordStr(bom.GoodsName)
}
//经过了最前面的参数匹配
//如果型号还是为空,则用参数去匹配,因为有可能参数里面填了型号
if bom.GoodsName == "" && bom.Attrs == "" {
continue
} else if bom.GoodsName == "" && bom.Attrs != "" {
bom.GoodsName = bom.Attrs
}
//模糊匹配之前要先去看这个bomItem的商品名称是否是由参数获取到的
//如果是的话,就不需要模糊匹配了,因为参数获取到的型号才是最符合参数的,如果再去模糊匹配,就不符合参数了
var paramsRawSearch bool
paramsRawSearch = rawSearch
if bom.IsGoodsNameByAttrs && rawSearch == false {
paramsRawSearch = true
}
//构建一个goods_name对应的bomItems列表
searchRequest := getSearchParams(index, bom, sort, paramsRawSearch)
searchFlag = true
search.Add(searchRequest)
}
//没有搜索条件的话,直接返回空值即可
if !searchFlag {
return nil, err
}
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 {
var goods model.Goods
err := json.Unmarshal(*hit.Source, &goods)
if err != nil {
return nil, err
}
if goods.GoodsName == "" {
break
}
var goodsMap GoodsMap
goodsMap.GoodsId = hit.Id
goodsMap.Amount = bomItems[key].Amount
goodsMap.Number = bomItems[key].Number
goodsMap.GoodsName = bomItems[key].GoodsName
goodsMap.BomItemId = bomItems[key].BomItemID
goodsMap.BomId = bomId
goodsMap.DeliveryType = deliveryType
goodsMapList = append(goodsMapList, goodsMap)
break
}
}
}
return
}
//构建请求参数
func getSearchParams(index string, bomItem model.BomItem, sort int, flag bool) (searchRequest *es.SearchRequest) {
query := getTermQuery(index, bomItem, sort, flag)
source := es.NewSearchSource().Query(query)
if sort == 1 {
source.Sort("_score", false)
source.Sort("sort", false)
source.Sort("stock", false)
source.Sort("single_price", true)
}
//要去判断sort,sort=2是按照价格排序
if sort == 2 {
source.Sort("_score", false)
source.Sort("single_price", true)
//sort=3是按照库存排序
} else if sort == 3 {
source.Sort("_score", false)
source.Sort("stock", false)
}
source = source.From(0).Size(1)
searchRequest = es.NewSearchRequest().Source(source)
//fmt.Println(searchRequest.Body())
return searchRequest
}
//构建term条件
func getTermQuery(index string, bomItem model.BomItem, sort int, flag bool) (query *es.BoolQuery) {
query = es.NewBoolQuery()
if flag {
field := "auto_goods_name.raw"
replace, _ := regexp.Compile("[^A-Za-z0-9]+")
goodsName := replace.ReplaceAllString(bomItem.GoodsName, "")
goodsName = strings.ToUpper(goodsName)
//商品名称太短的,限制搜索
if len(goodsName) <= 3 {
query = query.Filter(es.NewTermQuery(field, "€_€"))
} else {
query = query.Filter(es.NewTermQuery(field, goodsName))
}
//判断是否存在brandName并且匹配不到对应的标准品牌
if bomItem.BrandName != "" {
bomItem.BrandName = strings.ToUpper(bomItem.BrandName)
query = query.Should(es.NewConstantScoreQuery(es.NewTermQuery("brand_name", bomItem.BrandName)).Boost(2))
}
//搜索库存
query = query.Should(es.NewConstantScoreQuery(es.NewRangeQuery("stock").Gte(bomItem.Number * bomItem.Amount)))
} else {
field := "auto_goods_name"
query = query.Must(es.NewTermQuery(field, bomItem.GoodsName))
}
//对品牌进行判断搜索,如果能匹配到对应的自营标准品牌(那么同时也有对应的联营品牌)
//还要去判断当前索引是否包含自营,不包含,直接跳过自营的brand_id
if strings.Contains(index, "liexin_ziying") {
query.Should(es.NewTermQuery("brand_id", bomItem.ZyBrandId))
}
query.Must(es.NewRangeQuery("stock").Gt(0))
if bomItem.ZyBrandId != "" {
for _, id := range bomItem.LyBrandIds {
query.Should(es.NewTermQuery("brand_id", id))
}
}
//按价格排序
if sort == 2 {
query = query.Filter(es.NewRangeQuery("single_price").Gt(0))
}
//库存排序
if sort == 3 {
query = query.Filter(es.NewRangeQuery("stock").Gt(0))
}
if configs.ApiSetting.Mode != "debug" {
query = query.Filter(es.NewTermQuery("status", 1))
}
return query
}
package logic
import (
"bom_server/configs"
"bom_server/internal/common"
"bom_server/internal/model"
"context"
"encoding/json"
"fmt"
es "gopkg.in/olivere/elastic.v5"
"regexp"
"strings"
)
func search(index string, bomId int, bomItems []model.BomItem, deliveryType, sort int, client *es.Client, rawSearch bool) (goodsMapList []GoodsMap, err error) {
//先去自营查一遍
search := client.MultiSearch().Index(index)
//是否已经搜索过标签
searchFlag := false
//多重搜索,第一次先去精确匹配
for _, bom := range bomItems {
//如果是模糊查询,还要去截取字符串
if !rawSearch {
bom.GoodsName = common.SubKeyWordStr(bom.GoodsName)
}
if bom.GoodsName == "" && bom.Attrs == "" {
continue
}
//模糊匹配之前要先去看这个bomItem的商品名称是否是由参数获取到的
//如果是的话,就不需要模糊匹配了,因为参数获取到的型号才是最符合参数的,如果再去模糊匹配,就不符合参数了
var paramsRawSearch bool
paramsRawSearch = rawSearch
if bom.IsGoodsNameByAttrs && rawSearch == false {
paramsRawSearch = true
}
//构建一个goods_name对应的bomItems列表
searchRequest := getSearchParams(index, bom, sort, paramsRawSearch)
searchFlag = true
search.Add(searchRequest)
}
//没有搜索条件的话,直接返回空值即可
if !searchFlag {
return nil, err
}
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 {
var goods model.Goods
err := json.Unmarshal(*hit.Source, &goods)
if err != nil {
return nil, err
}
if goods.GoodsName == "" {
break
}
var goodsMap GoodsMap
goodsMap.GoodsId = hit.Id
goodsMap.Amount = bomItems[key].Amount
goodsMap.Number = bomItems[key].Number
goodsMap.GoodsName = bomItems[key].GoodsName
goodsMap.BomItemId = bomItems[key].BomItemID
goodsMap.BomId = bomId
goodsMap.DeliveryType = deliveryType
goodsMapList = append(goodsMapList, goodsMap)
break
}
}
}
return
}
//构建请求参数
func getSearchParams(index string, bomItem model.BomItem, sort int, flag bool) (searchRequest *es.SearchRequest) {
fmt.Println("商品名称 : ",bomItem.GoodsName)
fmt.Println("参数列表 : ",bomItem.AttrList)
fmt.Println("封装 : ",bomItem.Encap)
query := getTermQuery(bomItem, sort, flag)
source := es.NewSearchSource().Query(query)
if sort == 1 {
source.Sort("_score", false)
source.Sort("single_price", true)
}
//要去判断sort,sort=2是按照价格排序
if sort == 2 {
source.Sort("_score", false)
source.Sort("single_price", true)
//sort=3是按照库存排序
} else if sort == 3 {
source.Sort("_score", false)
source.Sort("stock", false)
}
source = source.From(0).Size(1)
searchRequest = es.NewSearchRequest().Source(source)
return searchRequest
}
//构建term条件
func getTermQuery(bomItem model.BomItem, sort int, flag bool) (query *es.BoolQuery) {
query = es.NewBoolQuery()
if flag {
field := "auto_goods_name.raw"
replace, _ := regexp.Compile("[^A-Za-z0-9]+")
goodsName := replace.ReplaceAllString(bomItem.GoodsName, "")
goodsName = strings.ToUpper(goodsName)
//商品名称太短的或者没有商品名称的,去搜索参数
if len(goodsName) <= 3 {
if len(bomItem.AttrList) > 0 {
var params []interface{}
for _, attr := range bomItem.AttrList {
params = append(params, attr)
}
query = query.Must(es.NewTermsQuery("attr_bom", params...))
} else {
query = query.Must(es.NewTermsQuery("attr_bom", "$_$"))
}
} else {
query = query.Filter(es.NewTermQuery(field, goodsName))
}
//判断是否存在brandName并且匹配不到对应的标准品牌
if bomItem.BrandName != "" {
bomItem.BrandName = strings.ToUpper(bomItem.BrandName)
query = query.Should(es.NewConstantScoreQuery(es.NewTermQuery("brand_name", bomItem.BrandName)).Boost(2))
}
//判断封装是否有,有的话,直接去搜索封装
if bomItem.Encap != "" {
query = query.Must(es.NewTermQuery("encap", bomItem.Encap))
}
//搜索库存
query = query.Should(es.NewConstantScoreQuery(es.NewRangeQuery("stock").Gte(bomItem.Number * bomItem.Amount)))
} else {
query = query.Must(es.NewTermQuery("auto_goods_name", bomItem.GoodsName))
}
//只显示库存大于0的数据
query.Must(es.NewRangeQuery("stock").Gt(0))
//按价格排序
if sort == 2 || sort == 1 {
query = query.Filter(es.NewRangeQuery("single_price").Gt(0))
}
//库存排序
if sort == 3 {
query = query.Filter(es.NewRangeQuery("stock").Gt(0))
}
if configs.ApiSetting.Mode != "debug" {
query = query.Filter(es.NewTermQuery("status", 1))
}
return query
}
......@@ -14,6 +14,7 @@ var KeywordRegular = map[string]string{
`(Mf|MF|mf)$`: "mF",
`(Uh|uh|μh|uH|UH)$`: "μH",
`(Mh|mh|mH|MH)$`: "mH",
`(Ma|ma|mA|MA)$`: "mA",
`(K)$`: "nF",
`(V|v)`: "V",
}
......
package mapping
var AttrBomTransformMapping = map[string]string{
"阻值(欧姆)": "OM",
"容值": "DR",
"电感值": "DGZ",
"额定电压": "EDDY",
"额定电流": "EDDL",
"功率": "GL",
"直流电阻(内阻)": "ZLNZ",
"精度": "JD",
"封装": "FZ",
"温漂系数(介质材料)": "WPXS",
}
package model
\ No newline at end of file
......@@ -13,6 +13,7 @@ type BomItem struct {
Number int `json:"number"`
Amount int `json:"amount"`
Attrs string `json:"attrs"`
AttrList []string `json:"-"`
Encap string `json:"encap"`
// ItemStatus 匹配状态 1:等待匹配 2:可购现货 3:待询价 4:需要修正
ItemStatus int `json:"item_status"`
......
package main
import "bom_server/internal/logic"
import (
"bom_server/configs"
"bom_server/internal/logic"
"bom_server/internal/model"
"bom_server/internal/pkg/gredis"
"flag"
"fmt"
)
func main() {
logic.ChangeUnit("100kr(1002) ")
var path string
flag.StringVar(&path, "config", "C:/laragon/usr/go/src/bom_server/conf/config.ini", "../conf/config.ini")
flag.Parse()
configs.Setup(path)
model.Setup()
gredis.Setup()
//logic.ChangeUnit("10KΩ(1002) ")
//logic.ChangeUnit("±1%")
result:=logic.TransformAttr("SMA(DO-214AC) ,SS34 肖特基二极管 40V/3A", "0603")
fmt.Println(result)
}
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