| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120 |
- package com.uas.search.service.impl;
- import static com.uas.search.constant.SearchConstants.GOODS_BR_NAME_CN_FIELD;
- import static com.uas.search.constant.SearchConstants.GOODS_BR_NAME_CN_UNTOKENIZED_FIELD;
- import static com.uas.search.constant.SearchConstants.GOODS_BR_NAME_EN_FIELD;
- import static com.uas.search.constant.SearchConstants.GOODS_BR_NAME_EN_UNTOKENIZED_FIELD;
- import static com.uas.search.constant.SearchConstants.GOODS_KI_NAME_CN_FIELD;
- import static com.uas.search.constant.SearchConstants.GOODS_KI_NAME_CN_UNTOKENIZED_FIELD;
- import static com.uas.search.constant.SearchConstants.GOODS_PR_PCMPCODE_FIELD;
- import static com.uas.search.constant.model.Sort.Field.PRICE;
- import static com.uas.search.constant.model.Sort.Field.RESERVE;
- import static com.uas.search.util.SearchUtils.getDocuments;
- import static com.uas.search.util.SearchUtils.releaseIndexSearcher;
- import com.alibaba.fastjson.JSONArray;
- import com.alibaba.fastjson.JSONObject;
- import com.uas.search.annotation.NotEmpty;
- import com.uas.search.constant.SearchConstants;
- import com.uas.search.constant.model.CollectField;
- import com.uas.search.constant.model.MultiValue;
- import com.uas.search.constant.model.PageParams;
- import com.uas.search.constant.model.PageParams.FilterField;
- import com.uas.search.constant.model.SPage;
- import com.uas.search.constant.model.SortPlus;
- import com.uas.search.exception.SearchException;
- import com.uas.search.grouping.DistinctGroupCollector;
- import com.uas.search.grouping.GoodsGroupCollector;
- import com.uas.search.model.Brand;
- import com.uas.search.model.Component;
- import com.uas.search.model.Goods;
- import com.uas.search.model.Kind;
- import com.uas.search.model.PCBGoods;
- import com.uas.search.model.TradeGoods;
- import com.uas.search.model.V_Products;
- import com.uas.search.service.SearchService;
- import com.uas.search.sort.StringFieldComparatorSource;
- import com.uas.search.util.ClassAndTableNameUtils;
- import com.uas.search.util.CollectionUtils;
- import com.uas.search.util.DocumentToObjectUtils;
- import com.uas.search.util.ObjectToDocumentUtils;
- import com.uas.search.util.SearchUtils;
- import com.uas.search.util.StringUtils;
- import java.io.IOException;
- import java.net.URLDecoder;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.Calendar;
- import java.util.Collections;
- import java.util.Comparator;
- import java.util.Date;
- import java.util.HashMap;
- import java.util.HashSet;
- import java.util.List;
- import java.util.Map;
- import java.util.Map.Entry;
- import java.util.Set;
- import java.util.stream.Collectors;
- import org.apache.lucene.document.Document;
- import org.apache.lucene.index.Term;
- import org.apache.lucene.sandbox.queries.DuplicateFilter;
- import org.apache.lucene.search.BooleanClause;
- import org.apache.lucene.search.BooleanClause.Occur;
- import org.apache.lucene.search.BooleanQuery;
- import org.apache.lucene.search.IndexSearcher;
- import org.apache.lucene.search.NumericRangeQuery;
- import org.apache.lucene.search.PrefixQuery;
- import org.apache.lucene.search.Query;
- import org.apache.lucene.search.ScoreDoc;
- import org.apache.lucene.search.Sort;
- import org.apache.lucene.search.SortField;
- import org.apache.lucene.search.SortField.Type;
- import org.apache.lucene.search.TermQuery;
- import org.apache.lucene.search.TopDocs;
- import org.apache.lucene.search.TotalHitCountCollector;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.stereotype.Service;
- /**
- * 搜索索引
- *
- * @author sunyj
- * @since 2016年8月5日 下午2:21:26
- */
- @Service
- public class SearchServiceImpl implements SearchService {
- /**
- * 获取联想词时返回的最大数目
- */
- private static final int SIMILAR_NUM = 20;
- /**
- * 获取联想词时返回的最大数目
- */
- private static final int SIMILAR_NUM_EIGHT = 8;
- /**
- * 所有物料
- */
- private static final String ALL_PRODUCTS = "all";
- /**
- * 标准物料
- */
- private static final String STANDARD_PRODUCTS = "standard";
- /**
- * 非标物料
- */
- private static final String NONSTANDARD_PRODUCTS = "nStandard";
- /**
- * 默认的页码
- */
- private static final int PAGE_INDEX = 1;
- /**
- * 默认每页的大小
- */
- private static final int PAGE_SIZE = 20;
- /**
- * 品牌、类目分词可能重复,取前2000个
- */
- private static final int DUPLICATE_PAGE_SIZE = 2000;
- private static Logger logger = LoggerFactory.getLogger(SearchServiceImpl.class);
- /**
- * 查询所有物料
- *
- * @param keyword 关键词
- * @param page 页码
- * @param size 尺寸
- * @param enUU 企业UU
- * @param type all 全部 standard 标准 nStandard 非标
- * @return idPage
- * @throws IOException 输入异常
- */
- @Override
- public SPage<Long> getProductIds(Long enUU, String keyword, Integer page, Integer size, String type, Boolean duplicate) throws IOException {
- List<Long> ids = new ArrayList<>();
- SPage<Document> documents = getProductDocuments(enUU, keyword, page, size, type, duplicate);
- SPage<Long> sPage = new SPage<>(documents.getTotalPage(), documents.getTotalElement(), documents.getPage(),
- documents.getSize(), documents.isFirst(), documents.isLast());
- for (Document document : documents.getContent()) {
- ids.add(Long.parseLong(document.get(SearchConstants.PRODUCT_PRIVATE_ID_FIELD)));
- }
- sPage.setContent(ids);
- return sPage;
- }
- /**
- * 查询所有物料(B2B)
- *
- * @return idPage
- * @throws IOException 输入异常
- */
- @Override
- public SPage<Long> getProductIdsB2B(String keyword, String tableName, Integer page, Integer size, String keywordSearchColumns, String filters, String multiValueField, String sort, String notEqualFilters, String multiValueNotField) throws IOException {
- Table_name tbName = null;
- if (!StringUtils.isEmpty(tableName)) {
- tbName = Table_name.valueOf(tableName.toUpperCase());
- }
- PageParams pageParams = new PageParams();
- if (page != null) {
- pageParams.setPage(page);
- }
- if (size != null) {
- pageParams.setSize(size);
- }
- List<String> keywordSearchColumnsList = null;
- if (!StringUtils.isEmpty(keywordSearchColumns)) {
- String[] strs = keywordSearchColumns.split(",");
- keywordSearchColumnsList = new ArrayList<>();
- for (String str : strs) {
- keywordSearchColumnsList.add(str);
- }
- }
- pageParams.setKeywordSearchColumns(keywordSearchColumnsList);
- Map<String, Object> filtersMap = new HashMap<>();
- if (!StringUtils.isEmpty(filters)) {
- filtersMap.putAll(JSONObject.parseObject(filters));
- }
- if (!StringUtils.isEmpty(multiValueField)) {
- JSONArray jsonArray = JSONObject.parseArray(multiValueField);
- for (int i = 0; i < jsonArray.size(); i++) {
- JSONObject jsonObject = jsonArray.getJSONObject(i);
- String field = jsonObject.getString("field");
- MultiValue multiValue = jsonObject.getObject("multiValue", MultiValue.class);
- filtersMap.put(field, multiValue);
- }
- }
- if (!StringUtils.isEmpty(sort)) {
- filtersMap.put(SearchConstants.SORT_KEY, JSONObject.parseArray(sort, Sort.class));
- }
- if (!CollectionUtils.isEmpty(filtersMap)) {
- pageParams.setCommonFilters(filtersMap);
- }
- Map<String, Object> notEqualFiltersMap = new HashMap<>();
- if (!StringUtils.isEmpty(notEqualFilters)) {
- notEqualFiltersMap.putAll(JSONObject.parseObject(notEqualFilters));
- }
- if (!StringUtils.isEmpty(multiValueNotField)) {
- JSONArray jsonArray = JSONObject.parseArray(multiValueNotField);
- for (int i = 0; i < jsonArray.size(); i++) {
- JSONObject jsonObject = jsonArray.getJSONObject(i);
- String field = jsonObject.getString("field");
- MultiValue multiValue = jsonObject.getObject("multiValue", MultiValue.class);
- notEqualFiltersMap.put(field, multiValue);
- }
- }
- if (!CollectionUtils.isEmpty(notEqualFiltersMap)) {
- pageParams.setNotEqualFilters(notEqualFiltersMap);
- }
- return searchIds(keyword, tbName, pageParams);
- }
- @Override
- public SPage<Long> searchIds(String keyword, Table_name tableName, PageParams pageParams) throws SearchException {
- IndexSearcher indexSearcher = SearchUtils.getIndexSearcher(tableName.value());
- // 获取单据的id
- List<Long> content = new ArrayList<>();
- try {
- // 获取该表keyword可以搜索的域
- List<String> keywordFields = null;
- // 若未指定,再获取实体类中所配置的
- if (pageParams != null && !CollectionUtils.isEmpty(pageParams.getKeywordSearchColumns())) {
- keywordFields = getKeywordFields(pageParams.getKeywordSearchColumns());
- } else {
- keywordFields = ClassAndTableNameUtils.getKeywordFields(tableName);
- }
- SPage<ScoreDoc> scoreDocPage = search(indexSearcher, keyword, tableName, keywordFields, true, pageParams);
- SPage<Long> sPage = convertSPage(scoreDocPage, Long.class);
- for (ScoreDoc scoreDoc : scoreDocPage.getContent()) {
- Document document = indexSearcher.doc(scoreDoc.doc);
- content.add(Long.valueOf(document.get(ClassAndTableNameUtils.getIdField(tableName))));
- }
- sPage.setContent(content);
- return sPage;
- } catch (NumberFormatException | IOException e) {
- throw new SearchException(e).setDetailedMessage(e);
- } finally {
- SearchUtils.releaseIndexSearcher(indexSearcher);
- }
- }
- private SPage<ScoreDoc> search(IndexSearcher indexSearcher, String keyword, Table_name tableName,
- List<String> keywordFields, Boolean tokenized, PageParams pageParams) throws IOException {
- if (CollectionUtils.isEmpty(keywordFields)) {
- throw new IllegalArgumentException("keywordFields不可为空");
- }
- SPage<ScoreDoc> sPage = new SPage<>();
- BooleanQuery booleanQuery = new BooleanQuery();
- Sort sort = null;
- if (keyword == null) {
- keyword = "";
- }
- // 关键词无效,即搜索所有的数据
- // 关键词带空格,进行与操作
- String[] strs = keyword.split(" ");
- for (String str : strs) {
- // keyword可能是哪些域,域之间进行或操作
- BooleanQuery booleanQuery2 = new BooleanQuery();
- for (String keywordField : keywordFields) {
- booleanQuery2.add(SearchUtils.regexpQuery(keywordField, str, tokenized), BooleanClause.Occur.SHOULD);
- }
- booleanQuery.add(booleanQuery2, BooleanClause.Occur.MUST);
- }
- // 分页信息
- if (pageParams == null) {
- sPage.setPage(PAGE_INDEX);
- sPage.setSize(PAGE_SIZE);
- sPage.setFirst(true);
- } else {
- int page = pageParams.getPage();
- if (page > 0) {
- sPage.setPage(page);
- } else {
- sPage.setPage(PAGE_INDEX);
- sPage.setFirst(true);
- }
- int size = pageParams.getSize();
- if (size > 0) {
- sPage.setSize(size);
- } else {
- sPage.setSize(PAGE_SIZE);
- }
- Map<String, Object> filters = pageParams.getCommonFilters();
- if (!CollectionUtils.isEmpty(filters)) {
- // 如果filter中开始时间和截止时间至少传了一个参数,说明需要对时间范围进行限定
- if (!StringUtils.isEmpty(filters.get(SearchConstants.FROM_DATE_KEY))
- || !StringUtils.isEmpty(filters.get(SearchConstants.END_DATE_KEY))) {
- // 开始时间初始化为1990.1.1
- Calendar calendar = Calendar.getInstance();
- calendar.set(1990, 0, 1);
- // 截止时间初始化为现在
- long fromTime = calendar.getTimeInMillis();
- long endTime = new Date().getTime();
- if (!StringUtils.isEmpty(filters.get(SearchConstants.FROM_DATE_KEY))) {
- fromTime = Long.parseLong(
- filters.remove(SearchConstants.FROM_DATE_KEY).toString());
- }
- if (!StringUtils.isEmpty(filters.get(SearchConstants.END_DATE_KEY))) {
- endTime = Long.parseLong(
- filters.remove(SearchConstants.END_DATE_KEY).toString());
- }
- String dateField = ClassAndTableNameUtils.getDateField(tableName);
- if (!StringUtils.isEmpty(dateField)) {
- booleanQuery.add(NumericRangeQuery.newLongRange(dateField, fromTime, endTime, true, true), BooleanClause.Occur.MUST);
- }
- }
- // 如果需要排序
- if (!StringUtils.isEmpty(filters.get(SearchConstants.SORT_KEY))) {
- Object sortObject = filters.remove(SearchConstants.SORT_KEY);
- List<SortPlus> sortList = null;
- if (sortObject instanceof ArrayList) {
- sortList = (List<SortPlus>) sortObject;
- }
- boolean sortFieldsIsNull = true;
- if (!CollectionUtils.isEmpty(sortList)) {
- SortField[] sortFields = new SortField[sortList.size()];
- for (int i = 0; i < sortList.size(); i++) {
- try {
- SortPlus s = sortList.get(i);
- SortField sortField = new SortField(s.getField(), getType(s), !s.isReverse());
- if (s.getMissingValue() != null) {
- sortField.setMissingValue(s.getMissingValue());
- }
- sortFields[i] = sortField;
- sortFieldsIsNull = true;
- } catch (ClassCastException e) {
- continue;
- }
- }
- sort = sortFieldsIsNull ? null : new Sort(sortFields);
- }
- }
- // 其他过滤条件,键即为相应的数据库字段名(field名)
- Set<Entry<String, Object>> entrySet = filters.entrySet();
- for (Entry<String, Object> entry : entrySet) {
- String key = entry.getKey();
- Object value = entry.getValue();
- // 拼接索引域名
- String field = key;
- /*
- * 对于明细、企业等所关联的表的数据,是以json格式存储的,搜索时可能会对明细等表中多个字段进行过滤,
- * 但是键都是明细等表在主表中所对应的字段名称,为了实现这样的过滤功能,需要将多个值放在com.uas.search.
- * b2b.model.MultiValue中, 作为filters中key-value的value传递过来
- */
- if (value instanceof MultiValue) {
- MultiValue multiValue = (MultiValue) value;
- List<Object> values = multiValue.getValues();
- Occur occur = multiValue.isOr() ? Occur.SHOULD : Occur.MUST;
- BooleanQuery booleanQuery2 = new BooleanQuery();
- for (Object object : values) {
- booleanQuery2.add(filterIgnoreCase(field, String.valueOf(object)), occur);
- }
- booleanQuery.add(booleanQuery2, Occur.FILTER);
- } else {
- if (value != null) {
- booleanQuery.add(filterIgnoreCase(field, String.valueOf(value)), Occur.FILTER);
- }
- }
- }
- }
- // 排除过滤
- Map<String, Object> notEqualFilters = pageParams.getNotEqualFilters();
- if (!CollectionUtils.isEmpty(notEqualFilters)) {
- Set<Entry<String, Object>> entrySet = notEqualFilters.entrySet();
- for (Entry<String, Object> entry : entrySet) {
- String key = entry.getKey();
- Object value = entry.getValue();
- String field = key;
- // 排除多个值
- if (value instanceof MultiValue) {
- MultiValue multiValue = (MultiValue) value;
- List<Object> values = multiValue.getValues();
- Occur occur = multiValue.isOr() ? Occur.SHOULD : Occur.MUST;
- BooleanQuery booleanQuery2 = new BooleanQuery();
- for (Object object : values) {
- booleanQuery2.add(SearchUtils.regexpQuery(field, String.valueOf(object), false), occur);
- }
- booleanQuery.add(booleanQuery2, Occur.MUST_NOT);
- } else {
- if (value != null) {
- booleanQuery.add(SearchUtils.regexpQuery(field, String.valueOf(value), false),
- Occur.MUST_NOT);
- }
- }
- }
- }
- }
- logger.info(booleanQuery.toString());
- TopDocs topDocs;
- // 如果页码不为1
- if (sPage.getPage() > 1) {
- TopDocs previousTopDocs = null;
- if (sort != null) {
- previousTopDocs = indexSearcher.search(booleanQuery, (sPage.getPage() - 1) * sPage.getSize(), sort);
- } else {
- previousTopDocs = indexSearcher.search(booleanQuery, (sPage.getPage() - 1) * sPage.getSize());
- }
- int totalHits = previousTopDocs.totalHits;
- ScoreDoc[] previousScoreDocs = previousTopDocs.scoreDocs;
- // 搜索结果为空时,返回空集
- if (totalHits == 0) {
- sPage.setTotalElement(totalHits);
- int totalPage = (int) Math.ceil(totalHits / (1.0 * sPage.getSize()));
- sPage.setTotalPage(totalPage);
- if (totalPage == sPage.getPage()) {
- sPage.setLast(true);
- }
- sPage.setContent(new ArrayList<ScoreDoc>());
- return sPage;
- }
- // 超出页码数时,返回第1页数据
- if ((sPage.getPage() - 1) * sPage.getSize() >= totalHits) {
- sPage.setPage(1);
- sPage.setFirst(true);
- if (sort != null) {
- topDocs = indexSearcher.search(booleanQuery, sPage.getSize(), sort);
- } else {
- topDocs = indexSearcher.search(booleanQuery, sPage.getSize());
- }
- }
- if (sort != null && sPage.getPage() > 1) {
- topDocs = indexSearcher.searchAfter(previousScoreDocs[previousScoreDocs.length - 1], booleanQuery,
- sPage.getSize(), sort);
- } else {
- topDocs = indexSearcher.searchAfter(previousScoreDocs[previousScoreDocs.length - 1], booleanQuery,
- sPage.getSize());
- }
- } else {
- sPage.setFirst(true);
- if (sort != null) {
- topDocs = indexSearcher.search(booleanQuery, sPage.getSize(), sort);
- } else {
- topDocs = indexSearcher.search(booleanQuery, sPage.getSize());
- }
- }
- int totalHits = topDocs.totalHits;
- // 设置总元素个数、页数等信息
- sPage.setTotalElement(totalHits);
- int totalPage = (int) Math.ceil(totalHits / (1.0 * sPage.getSize()));
- sPage.setTotalPage(totalPage);
- if (totalPage == sPage.getPage()) {
- sPage.setLast(true);
- }
- sPage.setContent(Arrays.asList(topDocs.scoreDocs));
- return sPage;
- }
- /**
- * 获取排序字段的类型
- *
- * @param s
- * @return
- */
- private SortField.Type getType(SortPlus s) {
- if (s == null) {
- return null;
- }
- SortPlus.Type type = s.getType();
- switch (type) {
- case STRING:
- return SortField.Type.STRING;
- case INT:
- return SortField.Type.INT;
- case FLOAT:
- return SortField.Type.FLOAT;
- case LONG:
- return SortField.Type.LONG;
- case DOUBLE:
- return SortField.Type.DOUBLE;
- default:
- throw new SearchException("排序参数错误:" + type);
- }
- }
- /**
- * @return 过滤时不区分大小写
- */
- private Query filterIgnoreCase(String field, String keyword){
- BooleanQuery booleanQuery = new BooleanQuery();
- booleanQuery.add(SearchUtils.regexpQuery(field, keyword, false), Occur.SHOULD);
- booleanQuery.add(SearchUtils.regexpQuery(field, keyword.toLowerCase(), false), Occur.SHOULD);
- return booleanQuery;
- }
- /**
- * 转换SPage
- *
- * @param scoreDocPage
- * @param clazz
- * @return
- */
- private <T> SPage<T> convertSPage(SPage<ScoreDoc> scoreDocPage, Class<T> clazz) {
- return new SPage<>(scoreDocPage.getTotalPage(), scoreDocPage.getTotalElement(), scoreDocPage.getPage(),
- scoreDocPage.getSize(), scoreDocPage.isFirst(), scoreDocPage.isLast());
- }
- /**
- * 获取指定的可以搜索的字段列名
- * @param keywordSearchColumns
- * keyword模糊搜索的字段名称
- * @return 可以搜索的字段列名
- */
- private List<String> getKeywordFields(List<String> keywordSearchColumns) {
- List<String> result = new ArrayList<>();
- for (String keywordSearchColumn : keywordSearchColumns) {
- // 返回之前先拼接索引域名
- result.add(keywordSearchColumn);
- }
- return result;
- }
- private SPage<Document> getProductDocuments(Long enUU, String keyword, Integer page, Integer size, String type, Boolean duplicate) throws IOException {
- // if (SearchUtils.isKeywordInvalid(keyword)) {
- // throw new IllegalArgumentException("搜索关键词无效:" + keyword);
- // }
- BooleanQuery q1 = new BooleanQuery();
- if (null != enUU) {
- q1.add(new TermQuery(new Term(SearchConstants.PRODUCT_PRIVATE_ENUU_FIELD, String.valueOf(enUU))), BooleanClause.Occur.MUST);
- }
- if (STANDARD_PRODUCTS.equals(type)) {
- q1.add(new TermQuery(new Term(SearchConstants.PRODUCT_PRIVATE_STANDARD_FIELD, String.valueOf(1))), BooleanClause.Occur.MUST);
- } else if (NONSTANDARD_PRODUCTS.equals(type)) {
- q1.add(new TermQuery(new Term(SearchConstants.PRODUCT_PRIVATE_STANDARD_FIELD, String.valueOf(0))), BooleanClause.Occur.MUST);
- }
- q1.add(new TermQuery(new Term(SearchConstants.PRODUCT_PRIVATE_B2CENABLED_FIELD, String.valueOf(1))), BooleanClause.Occur.MUST);
- BooleanQuery booleanQuery = new BooleanQuery();
- booleanQuery.add(q1, BooleanClause.Occur.MUST);
- if (!StringUtils.isEmpty(keyword)) {
- BooleanQuery q2 = new BooleanQuery();
- if (!duplicate) {
- q2.add(createQuery(SearchConstants.PRODUCT_PRIVATE_KIND_FIELD, keyword.toLowerCase(), true,1), BooleanClause.Occur.SHOULD);
- q2.add(createQuery(SearchConstants.PRODUCT_PRIVATE_PBRANDEN_FIELD, keyword.toLowerCase(), true,1), BooleanClause.Occur.SHOULD);
- }
- q2.add(createQuery(SearchConstants.PRODUCT_PRIVATE_PCMPCODE_FIELD, keyword.toLowerCase(), true,1), BooleanClause.Occur.SHOULD);
- booleanQuery.add(q2, BooleanClause.Occur.MUST);
- }
- if (Boolean.valueOf(duplicate)) {
- DuplicateFilter duplicateFilter = new DuplicateFilter(SearchConstants.PRODUCT_PRIVATE_PCMPCODE_FIELD);
- logger.info(booleanQuery.toString());
- return getDocuments(SearchConstants.PRODUCTS_PRIVATE_TABLE_NAME, booleanQuery, new Sort(sortProduct()), page, size, duplicateFilter);
- } else {
- logger.info(booleanQuery.toString());
- return getDocuments(SearchConstants.PRODUCTS_PRIVATE_TABLE_NAME, booleanQuery, new Sort(sortProduct()), page, size);
- }
- }
- /**
- * @return 物料排序规则
- */
- private SortField[] sortProduct() {
- List<SortField> sortFieldList = new ArrayList<>();
- // id
- sortFieldList.add(new SortField(SearchConstants.PRODUCT_PRIVATE_ID_FIELD, Type.LONG, true));
- sortFieldList.add(new SortField(SearchConstants.PRODUCT_PRIVATE_ATTACH_FIELD, Type.DOUBLE, true));
- SortField[] sortFields = new SortField[sortFieldList.size()];
- sortFieldList.toArray(sortFields);
- return sortFields;
- }
- @Override
- public SPage<Long> getKindIds(String keyword, Integer page, Integer size) throws IOException {
- List<Long> ids = new ArrayList<>();
- SPage<Document> documents = getKindDocuments(keyword, page, size);;
- SPage<Long> sPage = new SPage<>(documents.getTotalPage(), documents.getTotalElement(), documents.getPage(),
- documents.getSize(), documents.isFirst(), documents.isLast());
- for (Document document : documents.getContent()) {
- ids.add(Long.parseLong(document.get(SearchConstants.KIND_ID_FIELD)));
- }
- sPage.setContent(ids);
- return sPage;
- }
- @Override
- public SPage<Map<String, Object>> getKinds(String keyword, Integer page, Integer size) throws IOException {
- List<Map<String, Object>> kinds = new ArrayList<>();
- SPage<Document> documents = getKindDocuments(keyword, page, size);
- SPage<Map<String, Object>> sPage = new SPage<>(documents.getTotalPage(),
- documents.getTotalElement(), documents.getPage(), documents.getSize(), documents.isFirst(),
- documents.isLast());
- for (Document document : documents.getContent()) {
- Map<String, Object> kind = new HashMap<>();
- kind.put("id", Long.parseLong(document.get(SearchConstants.KIND_ID_FIELD)));
- kind.put("nameCn", document.get(SearchConstants.KIND_NAMECN_FIELD));
- kinds.add(kind);
- }
- sPage.setContent(kinds);
- return sPage;
- }
- private SPage<Document> getKindDocuments(String keyword, Integer page, Integer size) throws IOException {
- if (SearchUtils.isKeywordInvalid(keyword)) {
- throw new IllegalArgumentException("搜索关键词无效:" + keyword);
- }
- BooleanQuery booleanQuery = SearchUtils.getBooleanQuery(SearchConstants.KIND_NAMECN_FIELD, keyword);
- logger.info(booleanQuery.toString());
- return getDocuments(SearchConstants.KIND_TABLE_NAME, booleanQuery, new Sort(sortKind(keyword)), page, size);
- }
- /**
- * @return 类目排序规则
- */
- private SortField[] sortKind(String keyword) {
- // 分数 > 访问量 > 搜索次数
- return new SortField[]{
- sortField(SearchConstants.KIND_VISIT_COUNT_FIELD, Type.LONG, true, Long.MIN_VALUE),
- sortField(SearchConstants.KIND_SEARCH_COUNT_FIELD, Type.LONG, true, Long.MIN_VALUE),
- new SortField(SearchConstants.KIND_NAMECN_UNTOKENIZED_FIELD, new StringFieldComparatorSource(keyword))
- };
- }
- /**
- * 构造 SortField
- *
- * @param field Name of field to sort by. Can be <code>null</code> if
- * <code>type</code> is SCORE or DOC.
- * @param type Type of values in the terms.
- * @param reverse True if natural order should be reversed.
- * @param missingValue Used for 'sortMissingFirst/Last'
- * @return SortField
- */
- private SortField sortField(String field, Type type, boolean reverse, Object missingValue) {
- SortField sortField = new SortField(field, type, reverse);
- sortField.setMissingValue(missingValue);
- return sortField;
- }
- @Override
- public SPage<Long> getBrandIds(String keyword, Integer page, Integer size) throws IOException {
- List<Long> ids = new ArrayList<>();
- SPage<Document> documents = getBrandDocuments(keyword, page, size);
- SPage<Long> sPage = new SPage<>(documents.getTotalPage(), documents.getTotalElement(), documents.getPage(),
- documents.getSize(), documents.isFirst(), documents.isLast());
- for (Document document : documents.getContent()) {
- ids.add(Long.parseLong(document.get(SearchConstants.BRAND_ID_FIELD)));
- }
- sPage.setContent(ids);
- return sPage;
- }
- @Override
- public SPage<Map<String, Object>> getBrands(String keyword, Integer page, Integer size) throws IOException {
- List<Map<String, Object>> brands = new ArrayList<>();
- SPage<Document> documents = getBrandDocuments(keyword, page, size);
- SPage<Map<String, Object>> sPage = new SPage<Map<String, Object>>(documents.getTotalPage(),
- documents.getTotalElement(), documents.getPage(), documents.getSize(), documents.isFirst(),
- documents.isLast());
- for (Document document : documents.getContent()) {
- Map<String, Object> brand = new HashMap<String, Object>();
- brand.put("id", Long.parseLong(document.get(SearchConstants.BRAND_ID_FIELD)));
- brand.put("uuid", document.get(SearchConstants.BRAND_UUID_FIELD));
- brand.put("nameCn", document.get(SearchConstants.BRAND_NAMECN_FIELD));
- brand.put("nameEn", document.get(SearchConstants.BRAND_NAMEEN_FIELD));
- brands.add(brand);
- }
- sPage.setContent(brands);
- return sPage;
- }
- @Override
- public SPage<Map<String, Object>> getBrandsAndSellers(String keyword, Integer page, Integer size)
- throws IOException {
- List<Map<String, Object>> content = new ArrayList<>();
- Map<String, Object> map = new HashMap<>();
- List<Long> brandIds = new ArrayList<>();
- SPage<Object> stock = null;
- SPage<Object> futures = null;
- // 精准匹配
- SPage<Long> documents = getBrandIds(keyword, page, size, false);
- SPage<Map<String, Object>> sPage = new SPage<>(1, 1, 1, documents.getSize(), true, true);
- // 精准匹配成功
- if (!CollectionUtils.isEmpty(documents.getContent())) {
- Map<String, List<String>> keywordFeildsMap = new HashMap<>();
- List<String> goodsFeilds = new ArrayList<>();
- goodsFeilds.add(SearchConstants.GOODS_PR_PBRAND_EN_UNTOKENIZED_FIELD);
- goodsFeilds.add(SearchConstants.GOODS_PR_PBRAND_CN_UNTOKENIZED_FIELD);
- List<String> productsFeilds = new ArrayList<>();
- productsFeilds.add(SearchConstants.PRODUCT_PRIVATE_PBRAND_CN_FIELD);
- productsFeilds.add(SearchConstants.PRODUCT_PRIVATE_PBRAND_EN_FIELD);
- keywordFeildsMap.put("goods", goodsFeilds);
- keywordFeildsMap.put("products", productsFeilds);
- brandIds.add(documents.getContent().get(0));
- // 获取卖家信息
- Map<String, SPage<Object>> sellers = querySellers(keyword, keywordFeildsMap, page, size, false, SearchConstants.BRAND);
- stock = sellers.get("stock");
- futures = sellers.get("futures");
- map.put("stock", stock);
- map.put("futures", futures);
- // 模糊匹配
- } else {
- SPage<Long> brandPage = getBrandIds(keyword, page, size, true);
- brandIds = brandPage.getContent();
- if (CollectionUtils.isEmpty(brandIds)) {
- List<String> keywordFields = new ArrayList<>();
- keywordFields.add(SearchConstants.BRAND_NAMECN_FIELD);
- keywordFields.add(SearchConstants.BRAND_NAMEEN_FIELD);
- keyword = recursivelyBrands(keyword, keywordFields, true);
- brandPage = getBrandIds(keyword, page, size, true);
- brandIds = brandPage.getContent();
- }
- sPage = new SPage<>(brandPage.getTotalPage(), brandPage.getTotalElement(), brandPage.getPage(), brandPage.getSize(), brandPage.isFirst(), brandPage.isLast());
- }
- map.put("brandIds", brandIds);
- content.add(map);
- sPage.setContent(content);
- return sPage;
- }
- @Override
- public Map<String, Object> getSellersWithKind(String keyword, Integer page, Integer size)
- throws IOException {
- Map<String, Object> map = new HashMap<>();
- SPage<Object> stock = null;
- SPage<Object> futures = null;
- Map<String, List<String>> keywordFeildsMap = new HashMap<>();
- List<String> goodsFeilds = new ArrayList<>();
- goodsFeilds.add(SearchConstants.GOODS_PR_KIND_FIELD);
- List<String> productsFeilds = new ArrayList<>();
- productsFeilds.add(SearchConstants.PRODUCT_PRIVATE_KIND_FIELD);
- keywordFeildsMap.put("goods", goodsFeilds);
- keywordFeildsMap.put("products", productsFeilds);
- Map<String, SPage<Object>> sellers = querySellers(keyword, keywordFeildsMap, page, size, true, SearchConstants.KIND);
- stock = sellers.get("stock");
- futures = sellers.get("futures");
- map.put("stock", stock);
- map.put("futures", futures);
- return map;
- }
- /**
- * 获取品牌id
- * @param keyword
- * @param page
- * @param size
- * @return
- */
- private SPage<Long> getBrandIds(String keyword, Integer page, Integer size, Boolean tokenized) throws IOException{
- List<Long> brandIds = new ArrayList<>();
- if (SearchUtils.isKeywordInvalid(keyword)) {
- throw new IllegalArgumentException("搜索关键词无效:" + keyword);
- }
- List<String> keywordFields = new ArrayList<>();
- if (tokenized) {
- keywordFields.add(SearchConstants.BRAND_NAMECN_FIELD);
- keywordFields.add(SearchConstants.BRAND_NAMEEN_FIELD);
- } else {
- keywordFields.add(SearchConstants.BRAND_NAMECN_UNTOKENIZED_FIELD);
- keywordFields.add(SearchConstants.BRAND_NAMEEN_UNTOKENIZED_FIELD);
- }
- BooleanQuery booleanQuery = queryBrands(keyword, keywordFields, tokenized);
- logger.info(booleanQuery.toString());
- SPage<Document> documents = getDocuments(SearchConstants.BRAND_TABLE_NAME, booleanQuery, new Sort(sortBrand(keyword)), page,
- size);
- SPage<Long> sPage = new SPage<Long>(documents.getTotalPage(),
- documents.getTotalElement(), documents.getPage(), documents.getSize(), documents.isFirst(),
- documents.isLast());
- for (Document document : documents.getContent()) {
- brandIds.add(Long.parseLong(document.get(SearchConstants.BRAND_ID_FIELD)));
- }
- sPage.setContent(brandIds);
- return sPage;
- }
- private BooleanQuery queryBrands(String keyword, List<String> keywordFields, Boolean tokenized) {
- BooleanQuery booleanQuery = new BooleanQuery();
- if (!SearchUtils.isKeywordInvalid(keyword) && !CollectionUtils.isEmpty(keywordFields)) {
- for (String keywordField : keywordFields) {
- if (tokenized) {
- booleanQuery.add(SearchUtils.getBooleanQuery(keywordField, keyword.toLowerCase()),
- BooleanClause.Occur.SHOULD);
- } else {
- booleanQuery.add(new TermQuery(new Term(keywordField, keyword.toLowerCase())), Occur.SHOULD);
- }
- }
- }
- return booleanQuery;
- }
- /**
- * 获取品牌Document
- * @param keyword 关键词
- * @param page 页码
- * @param size 页数
- * @return
- * @throws IOException
- */
- private SPage<Document> getBrandDocuments(String keyword, Integer page, Integer size) throws IOException {
- if (SearchUtils.isKeywordInvalid(keyword)) {
- throw new IllegalArgumentException("搜索关键词无效:" + keyword);
- }
- BooleanQuery booleanQuery = new BooleanQuery();
- booleanQuery.add(SearchUtils.getBooleanQuery(SearchConstants.BRAND_NAMECN_FIELD, keyword),
- BooleanClause.Occur.SHOULD);
- booleanQuery.add(SearchUtils.getBooleanQuery(SearchConstants.BRAND_NAMEEN_FIELD, keyword),
- BooleanClause.Occur.SHOULD);
- logger.info(booleanQuery.toString());
- return getDocuments(SearchConstants.BRAND_TABLE_NAME, booleanQuery, new Sort(sortBrand(keyword)), page,
- size);
- }
- /**
- * @return 品牌排序规则
- */
- private SortField[] sortBrand(String keyword) {
- // 自定义排序 > 权重 > 访问量 > 搜索次数 > 分数
- // 分数排序放在最后,是因为有的中英文名称相同,分数翻倍,但实际匹配度并不高
- return new SortField[]{
- sortField(SearchConstants.BRAND_WEIGHT_FIELD, Type.DOUBLE, true, Double.MIN_VALUE),
- sortField(SearchConstants.BRAND_VISIT_COUNT_FIELD, Type.LONG, true, Long.MIN_VALUE),
- sortField(SearchConstants.BRAND_SEARCH_COUNT_FIELD, Type.LONG, true, Long.MIN_VALUE),
- new SortField(SearchConstants.BRAND_NAMEEN_UNTOKENIZED_FIELD, new StringFieldComparatorSource(keyword, true)),
- new SortField(SearchConstants.BRAND_NAMECN_UNTOKENIZED_FIELD, new StringFieldComparatorSource(keyword))
- };
- }
- @Override
- public Map<String, Object> getComponentIds(String keyword, PageParams pageParams) {
- Map<String, Object> searchComponentIds = getComponentIds(keyword, pageParams, null, null);
- return searchComponentIds;
- // TODO 对品牌、类目甚至拼音混合搜索(待完善)
- // int total = (int) searchComponentIds.get("total");
- // if (total != 0) {
- // return searchComponentIds;
- // }
- // List<Long> kindIds = getKindIds(keyword, Occur.SHOULD);
- // List<Long> brandIds = getBrandIds(keyword, Occur.SHOULD);
- // return getComponentIds(null, pageParams, kindIds, brandIds);
- }
- /**
- * 根据关键词搜索产品
- *
- * @param keyword
- * @param pageParams
- * @param kindIds
- * @param brandIds
- * @return
- */
- private Map<String, Object> getComponentIds(String keyword, PageParams pageParams, List<Long> kindIds,
- List<Long> brandIds) {
- // 因为器件、属性值的数据量远比类目、品牌大得多,而且器件搜索可能还需进行分页,
- // 所以涉及器件、属性值的搜索,大都不能像类目和品牌一样直接利用SearchUtils.getDocuments方法
- IndexSearcher indexSearcher = SearchUtils.getIndexSearcher(SearchConstants.COMPONENT_TABLE_NAME);
- if (pageParams == null) {
- pageParams = new PageParams();
- }
- if (pageParams.getPage() <= 0)
- pageParams.setPage(1);
- if (pageParams.getSize() <= 0)
- pageParams.setSize(20);
- Map<String, Object> map = new HashMap<>();
- List<Long> ids = new ArrayList<>();
- try {
- BooleanQuery booleanQuery = new BooleanQuery();
- if (!SearchUtils.isKeywordInvalid(keyword)) {
- booleanQuery.add(setBoost(keyword), BooleanClause.Occur.MUST);
- }
- Map<FilterField, Object> filters = pageParams.getFilters();
- if (!CollectionUtils.isEmpty(filters)) {
- // 筛选类目
- if (!StringUtils.isEmpty(filters.get(FilterField.COMPONENT_KINDID))) {
- String kindId = filters.get(FilterField.COMPONENT_KINDID).toString();
- TermQuery kindQuery = new TermQuery(new Term(SearchConstants.COMPONENT_KI_ID_FIELD, kindId));
- booleanQuery.add(kindQuery, BooleanClause.Occur.MUST);
- }
- // 筛选品牌
- if (!StringUtils.isEmpty(filters.get(FilterField.COMPONENT_BRANDID))) {
- String brandId = filters.get(FilterField.COMPONENT_BRANDID).toString();
- TermQuery brandQuery = new TermQuery(new Term(SearchConstants.COMPONENT_BR_ID_FIELD, brandId));
- booleanQuery.add(brandQuery, BooleanClause.Occur.MUST);
- }
- // 库存不为0
- if (!StringUtils.isEmpty(filters.get(FilterField.COMPONENT_HAS_RESERVE))) {
- Boolean isReserveNotEmpty = (Boolean) filters.get(FilterField.COMPONENT_HAS_RESERVE);
- if (isReserveNotEmpty) {
- booleanQuery.add(NumericRangeQuery.newDoubleRange(SearchConstants.COMPONENT_RESERVE_FIELD, 0.0,
- Double.MAX_VALUE, false, true), BooleanClause.Occur.MUST);
- }
- }
- // 现货、呆滞库存、样品数量不为0,取或的关系
- if (!StringUtils.isEmpty(filters.get(FilterField.COMPONENT_HAS_SAMPLE))
- || !StringUtils.isEmpty(filters.get(FilterField.COMPONENT_HAS_ORIGINAL))
- || !StringUtils.isEmpty(filters.get(FilterField.COMPONENT_HAS_INACTION_STOCK))) {
- BooleanQuery booleanQuery2 = new BooleanQuery();
- if (!StringUtils.isEmpty(filters.get(FilterField.COMPONENT_HAS_SAMPLE))) {
- booleanQuery2.add(NumericRangeQuery.newDoubleRange(SearchConstants.COMPONENT_SAMPLE_QTY_FIELD,
- 0.0, Double.MAX_VALUE, false, true), BooleanClause.Occur.SHOULD);
- }
- if (!StringUtils.isEmpty(filters.get(FilterField.COMPONENT_HAS_ORIGINAL))) {
- booleanQuery2.add(NumericRangeQuery.newDoubleRange(SearchConstants.COMPONENT_ORIGINAL_QTY_FIELD,
- 0.0, Double.MAX_VALUE, false, true), BooleanClause.Occur.SHOULD);
- }
- if (!StringUtils.isEmpty(filters.get(FilterField.COMPONENT_HAS_INACTION_STOCK))) {
- booleanQuery2.add(
- NumericRangeQuery.newDoubleRange(SearchConstants.COMPONENT_INACTION_STOCK_QTY_FIELD,
- 0.0, Double.MAX_VALUE, false, true),
- BooleanClause.Occur.SHOULD);
- }
- booleanQuery.add(booleanQuery2, Occur.MUST);
- }
- // 属性过滤
- if (!StringUtils.isEmpty(filters.get(FilterField.COMPONENT_PROPERTIES))) {
- JSONObject proJSON = JSONObject
- .parseObject(String.valueOf(filters.get(FilterField.COMPONENT_PROPERTIES)));
- for (String key : proJSON.keySet()) {
- String value = String.valueOf(proJSON.get(key));
- if (!StringUtils.isEmpty(value)) {
- if (!key.startsWith(SearchConstants.COMPONENT_PROPERTY_PREFIX)) {
- key = SearchConstants.COMPONENT_PROPERTY_PREFIX + key;
- }
- TermQuery propertyQuery = new TermQuery(new Term(key, value));
- booleanQuery.add(propertyQuery, BooleanClause.Occur.MUST);
- }
- }
- }
- }
- if (!CollectionUtils.isEmpty(kindIds)) {
- BooleanQuery booleanQuery2 = new BooleanQuery();
- for (Long id : kindIds) {
- booleanQuery2.add(new TermQuery(new Term(SearchConstants.COMPONENT_KI_ID_FIELD, id.toString())),
- Occur.SHOULD);
- }
- booleanQuery.add(booleanQuery2, Occur.MUST);
- }
- if (!CollectionUtils.isEmpty(brandIds)) {
- BooleanQuery booleanQuery2 = new BooleanQuery();
- for (Long id : brandIds) {
- booleanQuery2.add(new TermQuery(new Term(SearchConstants.COMPONENT_BR_ID_FIELD, id.toString())),
- Occur.SHOULD);
- }
- booleanQuery.add(booleanQuery2, Occur.MUST);
- }
- logger.info(booleanQuery.toString());
- Sort sort = new Sort(sortComponent(keyword));
- TopDocs hits;
- if (pageParams.getPage() > 1) {// 不是第一页
- TopDocs previousHits = indexSearcher.search(booleanQuery,
- (pageParams.getPage() - 1) * pageParams.getSize(), sort, true, false);
- ScoreDoc[] previousScoreDocs = previousHits.scoreDocs;
- ScoreDoc after = previousScoreDocs[previousScoreDocs.length - 1];
- hits = indexSearcher.searchAfter(after, booleanQuery, pageParams.getSize(), sort, true, false);
- } else {
- hits = indexSearcher.search(booleanQuery, pageParams.getSize(), sort, true, false);
- }
- ScoreDoc[] scoreDocs = hits.scoreDocs;
- for (ScoreDoc scoreDoc : scoreDocs) {
- // 数据量太大,需要指定将获取的数据(以免载入不必要的数据,降低速度)
- Set<String> fieldsToLoad = new HashSet<>();
- fieldsToLoad.add(SearchConstants.COMPONENT_ID_FIELD);
- Document document = indexSearcher.doc(scoreDoc.doc, fieldsToLoad);
- String componentId = document.get(SearchConstants.COMPONENT_ID_FIELD);
- ids.add(Long.parseLong(componentId));
- // System.out.println(componentId + "\t" + scoreDoc.score);
- }
- map.put("componentIds", ids);
- map.put("page", pageParams.getPage());
- map.put("size", pageParams.getSize());
- map.put("total", hits.totalHits);
- } catch (IOException e) {
- logger.error("", e);
- } finally {
- releaseIndexSearcher(indexSearcher);
- }
- return map;
- }
- /**
- * 同时搜索器件、类目、品牌,并设置boost
- *
- * @param keyword
- * @return
- */
- private Query setBoost(String keyword) {
- BooleanQuery booleanQuery = new BooleanQuery();
- PrefixQuery prefixQuery = new PrefixQuery(
- new Term(SearchConstants.COMPONENT_CODE_FIELD, keyword.toLowerCase()));
- prefixQuery.setBoost(100);
- booleanQuery.add(prefixQuery, BooleanClause.Occur.SHOULD);
- booleanQuery.add(createQuery(SearchConstants.COMPONENT_BR_NAMECN_FIELD, keyword, 10), BooleanClause.Occur.SHOULD);
- booleanQuery.add(createQuery(SearchConstants.COMPONENT_BR_NAMEEN_FIELD, keyword, 10), BooleanClause.Occur.SHOULD);
- booleanQuery.add(createQuery(SearchConstants.COMPONENT_KI_NAME_FIELD, keyword, 1), BooleanClause.Occur.SHOULD);
- return booleanQuery;
- }
- /**
- * @return 器件排序规则
- */
- private SortField[] sortComponent(String keyword) {
- // 分数 > 器件(访问量 > 搜索次数) > 品牌(权重 > 访问量 > 搜索次数) > 类目(访问量 > 搜索次数)
- return new SortField[]{
- sortField(SearchConstants.COMPONENT_WEIGHT_FIELD, Type.DOUBLE, true, Double.MIN_VALUE),
- sortField(SearchConstants.COMPONENT_VISIT_COUNT_FIELD, Type.LONG, true, Long.MIN_VALUE),
- sortField(SearchConstants.COMPONENT_SEARCH_COUNT_FIELD, Type.LONG, true, Long.MIN_VALUE),
- sortField(SearchConstants.COMPONENT_BR_WEIGHT_FIELD, Type.DOUBLE, true, Double.MIN_VALUE),
- sortField(SearchConstants.COMPONENT_BR_VISIT_COUNT_FIELD, Type.LONG, true, Long.MIN_VALUE),
- sortField(SearchConstants.COMPONENT_BR_SEARCH_COUNT_FIELD, Type.LONG, true, Long.MIN_VALUE),
- sortField(SearchConstants.COMPONENT_KI_VISIT_COUNT_FIELD, Type.LONG, true, Long.MIN_VALUE),
- sortField(SearchConstants.COMPONENT_KI_SEARCH_COUNT_FIELD, Type.LONG, true, Long.MIN_VALUE),
- new SortField(SearchConstants.COMPONENT_CODE_FIELD, new StringFieldComparatorSource(keyword, true)),
- new SortField(SearchConstants.COMPONENT_BR_NAMEEN_UNTOKENIZED_FIELD, new StringFieldComparatorSource(keyword, true)),
- new SortField(SearchConstants.COMPONENT_BR_NAMECN_UNTOKENIZED_FIELD, new StringFieldComparatorSource(keyword, true)),
- new SortField(SearchConstants.COMPONENT_KI_NAME_UNTOKENIZED_FIELD, new StringFieldComparatorSource(keyword))
- };
- }
- @Override
- public Set<Long> getKindIdsBySearchComponent(String keyword, String brandId) {
- Query filter = null;
- // 筛选品牌
- if (!StringUtils.isEmpty(brandId)) {
- filter = new TermQuery(new Term(SearchConstants.COMPONENT_BR_ID_FIELD, brandId));
- }
- return collectBySearchComponent(keyword, filter, SearchConstants.COMPONENT_KI_ID_FIELD).getValues();
- }
- @Override
- public Set<Map<String, Object>> getKindsBySearchComponent(String keyword, String brandId) {
- Query filter = null;
- // 筛选品牌
- if (!StringUtils.isEmpty(brandId)) {
- filter = new TermQuery(new Term(SearchConstants.COMPONENT_BR_ID_FIELD, brandId));
- }
- return collectBySearchComponent(keyword, filter, SearchConstants.KIND_ID_FIELD,
- new DistinctGroupCollector.CollectField(SearchConstants.KIND_ID_FIELD, "id"),
- new DistinctGroupCollector.CollectField(SearchConstants.KIND_NAMECN_FIELD, "nameCn"))
- .getCollectValues();
- }
- @Override
- public Set<Long> getBrandIdsBySearchComponent(String keyword, String kindId) {
- Query filter = null;
- // 筛选类目
- if (!StringUtils.isEmpty(kindId)) {
- filter = new TermQuery(new Term(SearchConstants.COMPONENT_KI_ID_FIELD, kindId));
- }
- return collectBySearchComponent(keyword, filter, SearchConstants.COMPONENT_BR_ID_FIELD).getValues();
- }
- @Override
- public Set<Map<String, Object>> getBrandsBySearchComponent(String keyword, String kindId) {
- Query filter = null;
- // 筛选类目
- if (!StringUtils.isEmpty(kindId)) {
- filter = new TermQuery(new Term(SearchConstants.COMPONENT_KI_ID_FIELD, kindId));
- }
- return collectBySearchComponent(keyword, filter, SearchConstants.COMPONENT_BR_ID_FIELD,
- new DistinctGroupCollector.CollectField(SearchConstants.COMPONENT_BR_ID_FIELD, "id"),
- new DistinctGroupCollector.CollectField(SearchConstants.COMPONENT_BR_UUID_FIELD, "uuid"),
- new DistinctGroupCollector.CollectField(SearchConstants.COMPONENT_BR_NAMECN_FIELD, "nameCn"))
- .getCollectValues();
- }
- /**
- * 搜索器件时统计指定信息
- *
- * @param keyword 关键词
- * @param filter 过滤条件
- * @param groupField 统计的单个字段(多为 id)
- * @param collectFields 统计的多个字段(详细信息),可为空
- * @return 统计信息
- */
- private DistinctGroupCollector collectBySearchComponent(String keyword, Query filter, String groupField, DistinctGroupCollector.CollectField... collectFields){
- if (SearchUtils.isKeywordInvalid(keyword)) {
- throw new IllegalArgumentException("搜索关键词无效:" + keyword);
- }
- IndexSearcher indexSearcher = SearchUtils.getIndexSearcher(SearchConstants.COMPONENT_TABLE_NAME);
- try {
- BooleanQuery booleanQuery = new BooleanQuery();
- keyword = URLDecoder.decode(keyword, "UTF-8");
- booleanQuery.add(setBoost(keyword), BooleanClause.Occur.MUST);
- if(filter != null){
- booleanQuery.add(filter, Occur.FILTER);
- }
- logger.info(booleanQuery.toString());
- DistinctGroupCollector collector = new DistinctGroupCollector(groupField, collectFields);
- indexSearcher.search(booleanQuery, collector);
- return collector;
- } catch (IOException e) {
- throw new IllegalStateException("统计失败", e);
- } finally {
- releaseIndexSearcher(indexSearcher);
- }
- }
- @Override
- public List<String> getSimilarKeywords(String keyword, Integer size) {
- size = size == null || size < 1 ? SIMILAR_NUM : size;
- List<String> result = new ArrayList<>();
- // 相似的器件原厂型号数量足够,直接返回
- List<String> componentCodes = getSimilarComponentCodes(keyword, size);
- result.addAll(componentCodes);
- removeDuplicate(result);
- if (result.size() == size) {
- return result;
- }
- // 获取相似类目
- List<String> kindNames = getSimilarKindNames(keyword, size);
- if (!CollectionUtils.isEmpty(kindNames)) {
- result.addAll(kindNames);
- removeDuplicate(result);
- // 如果总的数量超出SIMILAR_NUM,去除多余的元素
- if (result.size() > size) {
- removeElements(result, size);
- return result;
- }
- }
- // 获取相似品牌
- List<String> brandNames = getSimilarBrandNames(keyword, size);
- if (!CollectionUtils.isEmpty(brandNames)) {
- result.addAll(brandNames);
- removeDuplicate(result);
- if (result.size() > size) {
- removeElements(result, size);
- return result;
- }
- }
- return result;
- }
- @Override
- public List<Map<String, Object>> getSimilarComponents(String componentCode, Integer size) {
- size = size == null || size < 1 ? SIMILAR_NUM : size;
- if (SearchUtils.isKeywordInvalid(componentCode)) {
- throw new IllegalArgumentException("输入无效:" + componentCode);
- }
- IndexSearcher indexSearcher = SearchUtils.getIndexSearcher(SearchConstants.COMPONENT_TABLE_NAME);
- List<Map<String, Object>> components = new ArrayList<>();
- try {
- PrefixQuery prefixQuery = new PrefixQuery(
- new Term(SearchConstants.COMPONENT_CODE_FIELD, componentCode.toLowerCase()));
- logger.info(prefixQuery.toString());
- Sort sort = new Sort(new SortField(SearchConstants.COMPONENT_CODE_FIELD, new StringFieldComparatorSource(componentCode)));
- TopDocs hits = indexSearcher.search(prefixQuery, size, sort);
- ScoreDoc[] scoreDocs = hits.scoreDocs;
- for (ScoreDoc scoreDoc : scoreDocs) {
- Set<String> fieldsToLoad = new HashSet<>();
- fieldsToLoad.add(SearchConstants.COMPONENT_ID_FIELD);
- fieldsToLoad.add(SearchConstants.COMPONENT_UUID_FIELD);
- fieldsToLoad.add(SearchConstants.COMPONENT_CODE_FIELD);
- Document document = indexSearcher.doc(scoreDoc.doc, fieldsToLoad);
- Map<String, Object> map = new HashMap<>();
- map.put("id", Long.parseLong(document.get(SearchConstants.COMPONENT_ID_FIELD)));
- map.put("uuid", document.get(SearchConstants.COMPONENT_UUID_FIELD));
- map.put("code", document.get(SearchConstants.COMPONENT_CODE_FIELD));
- components.add(map);
- }
- } catch (IOException e) {
- logger.error("", e);
- } finally {
- releaseIndexSearcher(indexSearcher);
- }
- return components;
- }
- @Override
- public List<Map<String, Object>> getSimilarProducts(String code, Integer size) {
- size = size == null || size < 1 ? SIMILAR_NUM : size;
- if (SearchUtils.isKeywordInvalid(code)) {
- throw new IllegalArgumentException("输入无效:" + code);
- }
- IndexSearcher indexSearcher = SearchUtils.getIndexSearcher(SearchConstants.PRODUCTS_PRIVATE_TABLE_NAME);
- List<Map<String, Object>> products = new ArrayList<>();
- try {
- String termCode = "";
- TermQuery termQuery = new TermQuery(new Term(SearchConstants.PRODUCT_PRIVATE_PCMPCODE_FIELD, code.toLowerCase()));
- TopDocs termHits = indexSearcher.search(termQuery, 1);
- if (termHits.totalHits > 0) {
- for (ScoreDoc scoreDoc : termHits.scoreDocs) {
- Set<String> fieldsToLoad = new HashSet<>();
- fieldsToLoad.add(SearchConstants.PRODUCT_PRIVATE_ID_FIELD);
- fieldsToLoad.add(SearchConstants.PRODUCT_PRIVATE_PCMPCODE_FIELD);
- Document document = indexSearcher.doc(scoreDoc.doc, fieldsToLoad);
- Map<String, Object> map = new HashMap<>();
- map.put("id", Long.parseLong(document.get(SearchConstants.PRODUCT_PRIVATE_ID_FIELD)));
- map.put("pcmpcode", document.get(SearchConstants.PRODUCT_PRIVATE_PCMPCODE_FIELD));
- termCode = String.valueOf(map.get("pcmpcode"));
- products.add(map);
- }
- }
- PrefixQuery prefixQuery = new PrefixQuery(
- new Term(SearchConstants.PRODUCT_PRIVATE_PCMPCODE_FIELD, code.toLowerCase()));
- logger.info(prefixQuery.toString());
- // 物料型号重复率过高,故先去重
- DuplicateFilter codeFilter = new DuplicateFilter(SearchConstants.PRODUCT_PRIVATE_PCMPCODE_FIELD);
- Sort sort = new Sort(new SortField(SearchConstants.PRODUCT_PRIVATE_PCMPCODE_FIELD, new StringFieldComparatorSource(code, true)));
- TopDocs hits = indexSearcher.search(prefixQuery, codeFilter, size * 2, sort, true, false);
- ScoreDoc[] scoreDocs = hits.scoreDocs;
- String pcmpcode = "";
- for (ScoreDoc scoreDoc : scoreDocs) {
- Set<String> fieldsToLoad = new HashSet<>();
- fieldsToLoad.add(SearchConstants.PRODUCT_PRIVATE_ID_FIELD);
- fieldsToLoad.add(SearchConstants.PRODUCT_PRIVATE_PCMPCODE_FIELD);
- Document document = indexSearcher.doc(scoreDoc.doc, fieldsToLoad);
- Map<String, Object> map = new HashMap<>();
- map.put("id", Long.parseLong(document.get(SearchConstants.PRODUCT_PRIVATE_ID_FIELD)));
- map.put("pcmpcode", document.get(SearchConstants.PRODUCT_PRIVATE_PCMPCODE_FIELD));
- if (!pcmpcode.equals(map.get("pcmpcode")) && !termCode.equals(map.get("pcmpcode"))) {
- products.add(map);
- pcmpcode = String.valueOf(map.get("pcmpcode"));
- }
- }
- } catch (IOException e) {
- logger.error("", e);
- } finally {
- releaseIndexSearcher(indexSearcher);
- }
- return products;
- }
- @Override
- public List<Map<String, Object>> getSimilarBrands(String brandName, Integer size) throws IOException {
- size = size == null || size < 1 ? SIMILAR_NUM : size;
- if (SearchUtils.isKeywordInvalid(brandName)) {
- throw new IllegalArgumentException("输入无效:" + brandName);
- }
- List<Map<String, Object>> brands = new ArrayList<Map<String, Object>>();
- // 品牌名称带有空格,并且中英文名并无一定顺序,因此对nameCn、nameEn均要搜索
- BooleanQuery booleanQuery = new BooleanQuery();
- // 搜索nameCn
- booleanQuery.add(SearchUtils.getBooleanQuery(SearchConstants.BRAND_NAMECN_FIELD, brandName),
- BooleanClause.Occur.SHOULD);
- // 搜索nameEn
- booleanQuery.add(SearchUtils.getBooleanQuery(SearchConstants.BRAND_NAMEEN_FIELD, brandName),
- BooleanClause.Occur.SHOULD);
- logger.info(booleanQuery.toString());
- Sort sort = new Sort(new SortField(SearchConstants.BRAND_NAMEEN_UNTOKENIZED_FIELD, new StringFieldComparatorSource(brandName)),
- new SortField(SearchConstants.BRAND_NAMECN_UNTOKENIZED_FIELD, new StringFieldComparatorSource(brandName)));
- List<Document> documents = getDocuments(SearchConstants.BRAND_TABLE_NAME, booleanQuery, sort, null, size)
- .getContent();
- for (Document document : documents) {
- Map<String, Object> brand = new HashMap<>();
- brand.put("id", Long.parseLong(document.get(SearchConstants.BRAND_ID_FIELD)));
- brand.put("uuid", document.get(SearchConstants.BRAND_UUID_FIELD));
- brand.put("nameCn", document.get(SearchConstants.BRAND_NAMECN_FIELD));
- brand.put("nameEn", document.get(SearchConstants.BRAND_NAMEEN_FIELD));
- brands.add(brand);
- }
- return brands;
- }
- @Override
- public List<Map<String, Object>> getSimilarKinds(String kindName, Integer size) throws IOException {
- size = size == null || size < 1 ? SIMILAR_NUM : size;
- return getSimilarKinds(kindName, null, null, size);
- }
- @Override
- public List<Map<String, Object>> getSimilarLeafKinds(String kindName, Integer size) throws IOException {
- size = size == null || size < 1 ? SIMILAR_NUM : size;
- return getSimilarKinds(kindName, (short) 1, null, size);
- }
- @Override
- public List<Map<String, Object>> getSimilarKindsByLevel(String kindName, Short level, Integer size) throws IOException {
- size = size == null || size < 1 ? SIMILAR_NUM : size;
- return getSimilarKinds(kindName, null, level, size);
- }
- /**
- * 根据输入的类目名获取联想词
- *
- * @param kindName
- * 类目名
- * @param isLeaf
- * 是否只获取末级类目
- * @param level
- * 指定的类目级别
- * @param size 指定的联想词数目
- * @return
- */
- private List<Map<String, Object>> getSimilarKinds(String kindName, Short isLeaf, Short level, Integer size) throws IOException {
- size = size == null || size < 1 ? SIMILAR_NUM : size;
- if (SearchUtils.isKeywordInvalid(kindName)) {
- throw new IllegalArgumentException("输入无效:" + kindName);
- }
- List<Map<String, Object>> kinds = new ArrayList<>();
- BooleanQuery booleanQuery = new BooleanQuery();
- booleanQuery.add(SearchUtils.getBooleanQuery(SearchConstants.KIND_NAMECN_FIELD, kindName),
- BooleanClause.Occur.MUST);
- if (isLeaf != null && isLeaf == 1) {
- booleanQuery.add(new TermQuery(new Term(SearchConstants.KIND_ISLEAF_FIELD, String.valueOf(isLeaf))),
- BooleanClause.Occur.MUST);
- } else {
- if (level != null && level > 0) {
- booleanQuery.add(new TermQuery(new Term(SearchConstants.KIND_LEVEL_FIELD, String.valueOf(level))),
- BooleanClause.Occur.MUST);
- }
- }
- logger.info(booleanQuery.toString());
- Sort sort = new Sort(new SortField(SearchConstants.KIND_NAMECN_UNTOKENIZED_FIELD, new StringFieldComparatorSource(kindName)));
- List<Document> documents = getDocuments(SearchConstants.KIND_TABLE_NAME, booleanQuery, sort, null, size).getContent();
- for (Document document : documents) {
- Map<String, Object> map = new HashMap<>();
- map.put("id", Long.parseLong(document.get(SearchConstants.KIND_ID_FIELD)));
- map.put("nameCn", document.get(SearchConstants.KIND_NAMECN_FIELD));
- map.put("isLeaf", Short.parseShort(document.get(SearchConstants.KIND_ISLEAF_FIELD)));
- map.put("level", Short.parseShort(document.get(SearchConstants.KIND_LEVEL_FIELD)));
- kinds.add(map);
- }
- return kinds;
- }
- @Override
- public List<Map<String, String>> getSimilarPropertyValues(Long kindId, Long propertyId, String keyword,
- Long topNum) {
- if (kindId == null || propertyId == null) {
- throw new IllegalArgumentException("类目id和属性id不能为空");
- }
- IndexSearcher indexSearcher = SearchUtils.getIndexSearcher(SearchConstants.COMPONENT_TABLE_NAME);
- String propertyIdString = String.valueOf(propertyId);
- if (!propertyIdString.startsWith(SearchConstants.COMPONENT_PROPERTY_PREFIX)) {
- propertyIdString = SearchConstants.COMPONENT_PROPERTY_PREFIX + propertyIdString;
- }
- propertyIdString = propertyIdString + SearchConstants.COMPONENT_PROPERTY_TOKENIZED_SUFFIX;
- if (keyword == null) {
- keyword = "";
- }
- if (topNum == null || topNum < 1) {
- topNum = (long) SIMILAR_NUM;
- }
- List<String> propertyValues = new ArrayList<>();
- try {
- BooleanQuery booleanQuery = new BooleanQuery();
- booleanQuery.add(new TermQuery(new Term(SearchConstants.COMPONENT_KI_ID_FIELD, String.valueOf(kindId))),
- BooleanClause.Occur.MUST);
- booleanQuery.add(new PrefixQuery(new Term(propertyIdString, keyword.toLowerCase())),
- BooleanClause.Occur.MUST);
- logger.info(booleanQuery.toString());
- // 如果只搜索topNum个结果,去除重复的属性值后,数目很可能是不够的
- TopDocs topDocs = indexSearcher.search(booleanQuery, SearchConstants.TOP_NUM);
- ScoreDoc[] scoreDocs = topDocs.scoreDocs;
- for (ScoreDoc scoreDoc : scoreDocs) {
- Set<String> fieldsToLoad = new HashSet<>();
- fieldsToLoad.add(propertyIdString);
- Document document = indexSearcher.doc(scoreDoc.doc, fieldsToLoad);
- String propertyValue = document.get(propertyIdString);
- if (!StringUtils.isEmpty(propertyValue) && !propertyValues.contains(propertyValue)) {
- propertyValues.add(propertyValue);
- }
- if (propertyValues.size() >= topNum) {
- break;
- }
- }
- } catch (IOException e) {
- logger.error("", e);
- } finally {
- releaseIndexSearcher(indexSearcher);
- }
- List<Map<String, String>> result = new ArrayList<>();
- for (String propertyValue : propertyValues) {
- Map<String, String> map = new HashMap<>();
- map.put("propertyValue", propertyValue);
- result.add(map);
- }
- return result;
- }
- @Override
- public Set<Map<String, Object>> getSimilarGoodsCode(String keyword, String storeType, Integer size) throws IOException {
- size = size == null || size < 1 ? SIMILAR_NUM : size;
- if (SearchUtils.isKeywordInvalid(keyword)) {
- throw new IllegalArgumentException("输入无效:" + keyword);
- }
- IndexSearcher indexSearcher = SearchUtils.getIndexSearcher(SearchConstants.GOODS_TABLE_NAME);
- Set<Map<String, Object>> goods = new HashSet<>();
- try {
- List<String> storeTypes = new ArrayList<>();
- BooleanQuery booleanQuery = new BooleanQuery();
- List<Long> status = Arrays.asList(TradeGoods.VALID_STATUS);
- filter(status, SearchConstants.GOODS_GO_STATUS_FIELD, booleanQuery);
- if (!StringUtils.isEmpty(storeType)) {
- storeTypes = Arrays.asList(storeType.split(","));
- }
- if (!CollectionUtils.isEmpty(storeTypes)) {
- filter(storeTypes, SearchConstants.GOODS_ST_TYPE_FIELD, booleanQuery);
- }
- DistinctGroupCollector.CollectField[] collectFields = new DistinctGroupCollector.CollectField[] {
- new DistinctGroupCollector.CollectField(SearchConstants.GOODS_PR_PCMPCODE_FIELD, SearchConstants.GOODS_PR_PCMPCODE_FIELD)
- };
- DistinctGroupCollector collector = new DistinctGroupCollector(SearchConstants.GOODS_PR_PCMPCODE_FIELD, collectFields);
- booleanQuery.add(new TermQuery(new Term(GOODS_PR_PCMPCODE_FIELD, keyword.toLowerCase())), BooleanClause.Occur.MUST);
- indexSearcher.search(booleanQuery, collector);
- goods.addAll(collector.getCollectValues());
- BooleanQuery booleanQueryPre = new BooleanQuery();
- filter(status, SearchConstants.GOODS_GO_STATUS_FIELD, booleanQueryPre);
- if (!CollectionUtils.isEmpty(storeTypes)) {
- filter(storeTypes, SearchConstants.GOODS_ST_TYPE_FIELD, booleanQueryPre);
- }
- booleanQueryPre.add(new PrefixQuery(new Term(GOODS_PR_PCMPCODE_FIELD, keyword.toLowerCase())), Occur.MUST);
- logger.info(booleanQueryPre.toString());
- indexSearcher.search(booleanQueryPre, collector);
- goods.addAll(collector.getCollectValues());
- } catch (IOException e) {
- logger.error("", e);
- } finally {
- releaseIndexSearcher(indexSearcher);
- }
- if (goods.size() > size) {
- goods = goods.stream().limit(size).collect(Collectors.toSet());
- }
- return goods;
- }
- @Override
- public Set<Map<String, Object>> getSimilarGoodsBrand(String keyword, String storeType, Integer size)
- throws IOException {
- size = size == null || size < 1 ? SIMILAR_NUM : size;
- if (SearchUtils.isKeywordInvalid(keyword)) {
- throw new IllegalArgumentException("输入无效:" + keyword);
- }
- IndexSearcher indexSearcher = SearchUtils.getIndexSearcher(SearchConstants.GOODS_TABLE_NAME);
- Set<Map<String, Object>> goods = new HashSet<>();
- try {
- List<String> storeTypes = new ArrayList<>();
- BooleanQuery booleanQuery = new BooleanQuery();
- List<Long> status = Arrays.asList(TradeGoods.VALID_STATUS);
- filter(status, SearchConstants.GOODS_GO_STATUS_FIELD, booleanQuery);
- if (!StringUtils.isEmpty(storeType)) {
- storeTypes = Arrays.asList(storeType.split(","));
- }
- if (!CollectionUtils.isEmpty(storeTypes)) {
- filter(storeTypes, SearchConstants.GOODS_ST_TYPE_FIELD, booleanQuery);
- }
- DistinctGroupCollector.CollectField[] collectFields = new DistinctGroupCollector.CollectField[] {
- new DistinctGroupCollector.CollectField(GOODS_BR_NAME_EN_UNTOKENIZED_FIELD, GOODS_BR_NAME_EN_UNTOKENIZED_FIELD)
- };
- DistinctGroupCollector collector = new DistinctGroupCollector(GOODS_BR_NAME_EN_UNTOKENIZED_FIELD, collectFields);
- BooleanQuery nameQuery = new BooleanQuery();
- nameQuery.add(new TermQuery(new Term(GOODS_BR_NAME_EN_UNTOKENIZED_FIELD, keyword.toLowerCase())), Occur.SHOULD);
- nameQuery.add(new TermQuery(new Term(GOODS_BR_NAME_CN_UNTOKENIZED_FIELD, keyword.toLowerCase())), Occur.SHOULD);
- booleanQuery.add(nameQuery, Occur.MUST);
- indexSearcher.search(booleanQuery, collector);
- goods.addAll(collector.getCollectValues());
- BooleanQuery booleanQueryPre = new BooleanQuery();
- filter(status, SearchConstants.GOODS_GO_STATUS_FIELD, booleanQueryPre);
- if (!CollectionUtils.isEmpty(storeTypes)) {
- filter(storeTypes, SearchConstants.GOODS_ST_TYPE_FIELD, booleanQueryPre);
- }
- BooleanQuery namePreQuery = new BooleanQuery();
- namePreQuery.add(new PrefixQuery(new Term(GOODS_BR_NAME_EN_UNTOKENIZED_FIELD, keyword.toLowerCase())), Occur.SHOULD);
- namePreQuery.add(new PrefixQuery(new Term(GOODS_BR_NAME_CN_UNTOKENIZED_FIELD, keyword.toLowerCase())), Occur.SHOULD);
- booleanQueryPre.add(namePreQuery, Occur.MUST);
- logger.info(booleanQueryPre.toString());
- indexSearcher.search(booleanQueryPre, collector);
- goods.addAll(collector.getCollectValues());
- } catch (IOException e) {
- logger.error("", e);
- } finally {
- releaseIndexSearcher(indexSearcher);
- }
- if (goods.size() > size) {
- goods = goods.stream().limit(size).collect(Collectors.toSet());
- }
- return goods;
- }
- @Override
- public Set<Map<String, Object>> getSimilarGoodsKind(String keyword, String storeType, Integer size)
- throws IOException {
- size = size == null || size < 1 ? SIMILAR_NUM : size;
- if (SearchUtils.isKeywordInvalid(keyword)) {
- throw new IllegalArgumentException("输入无效:" + keyword);
- }
- IndexSearcher indexSearcher = SearchUtils.getIndexSearcher(SearchConstants.GOODS_TABLE_NAME);
- Set<Map<String, Object>> goods = new HashSet<>();
- try {
- List<String> storeTypes = new ArrayList<>();
- BooleanQuery booleanQuery = new BooleanQuery();
- List<Long> status = Arrays.asList(TradeGoods.VALID_STATUS);
- filter(status, SearchConstants.GOODS_GO_STATUS_FIELD, booleanQuery);
- if (!StringUtils.isEmpty(storeType)) {
- storeTypes = Arrays.asList(storeType.split(","));
- }
- if (!CollectionUtils.isEmpty(storeTypes)) {
- filter(storeTypes, SearchConstants.GOODS_ST_TYPE_FIELD, booleanQuery);
- }
- DistinctGroupCollector.CollectField[] collectFields = new DistinctGroupCollector.CollectField[] {
- new DistinctGroupCollector.CollectField(GOODS_KI_NAME_CN_FIELD, GOODS_KI_NAME_CN_FIELD),
- };
- DistinctGroupCollector collector = new DistinctGroupCollector(GOODS_KI_NAME_CN_FIELD, collectFields);
- booleanQuery.add(new TermQuery(new Term(GOODS_KI_NAME_CN_UNTOKENIZED_FIELD, keyword.toLowerCase())), BooleanClause.Occur.MUST);
- indexSearcher.search(booleanQuery, collector);
- goods.addAll(collector.getCollectValues());
- BooleanQuery booleanQueryPre = new BooleanQuery();
- filter(status, SearchConstants.GOODS_GO_STATUS_FIELD, booleanQueryPre);
- if (!CollectionUtils.isEmpty(storeTypes)) {
- filter(storeTypes, SearchConstants.GOODS_ST_TYPE_FIELD, booleanQueryPre);
- }
- booleanQueryPre.add(new PrefixQuery(new Term(GOODS_KI_NAME_CN_FIELD, keyword.toLowerCase())), Occur.MUST);
- logger.info(booleanQueryPre.toString());
- indexSearcher.search(booleanQueryPre, collector);
- goods.addAll(collector.getCollectValues());
- } catch (IOException e) {
- logger.error("", e);
- } finally {
- releaseIndexSearcher(indexSearcher);
- }
- if (goods.size() > size) {
- goods = goods.stream().limit(size).collect(Collectors.toSet());
- }
- return goods;
- }
- /**
- * 根据输入获取相似的器件原厂型号
- *
- * @param componentCode
- * @param size 指定的联想词数目
- * @return
- */
- private List<String> getSimilarComponentCodes(String componentCode, Integer size) {
- return getSimilarValues(SearchConstants.COMPONENT_TABLE_NAME, SearchConstants.COMPONENT_CODE_FIELD,
- SearchConstants.COMPONENT_CODE_FIELD, componentCode.toLowerCase(), size, true);
- }
- /**
- * 根据输入获取相似的品牌名称
- *
- * @param brandName
- * @param size 指定的联想词数目
- * @return
- */
- private List<String> getSimilarBrandNames(String brandName, Integer size) {
- // 获取相似的中文品牌
- List<String> nameCns = getSimilarValues(SearchConstants.BRAND_TABLE_NAME, SearchConstants.BRAND_NAMECN_FIELD,
- SearchConstants.BRAND_NAMECN_UNTOKENIZED_FIELD, brandName, size, false);
- // 相似的中文品牌数量足够,直接返回
- if (nameCns != null && nameCns.size() == SIMILAR_NUM) {
- return nameCns;
- }
- List<String> names = nameCns;
- // 获取相似的英文品牌
- List<String> nameEns = getSimilarValues(SearchConstants.BRAND_TABLE_NAME, SearchConstants.BRAND_NAMEEN_FIELD,
- SearchConstants.BRAND_NAMEEN_UNTOKENIZED_FIELD, brandName, size, false);
- names.addAll(nameEns);
- return names;
- }
- /**
- * 根据输入获取相似的类目名称
- *
- * @param kindName
- * @param size 指定的联想词数目
- * @return
- */
- private List<String> getSimilarKindNames(String kindName, Integer size) {
- return getSimilarValues(SearchConstants.KIND_TABLE_NAME, SearchConstants.KIND_NAMECN_FIELD,
- SearchConstants.KIND_NAMECN_UNTOKENIZED_FIELD, kindName, size, false);
- }
- /**
- * 根据输入值获取该域相似的值
- *
- * @param tableName 表名
- * @param field 联想字段
- * @param sortField 排序字段
- * @param keyword 关键词
- * @param size 联想词数目
- * @param usePrefixQuery 是否使用 PrefixQuery
- * @return 联想词
- */
- private List<String> getSimilarValues(String tableName, String field, String sortField, String keyword, Integer size, boolean usePrefixQuery) {
- if (SearchUtils.isKeywordInvalid(keyword)) {
- throw new IllegalArgumentException("输入无效:" + keyword);
- }
- IndexSearcher indexSearcher = SearchUtils.getIndexSearcher(tableName);
- List<String> result = new ArrayList<>();
- try {
- Query query;
- if(usePrefixQuery){
- query = new PrefixQuery(new Term(field, keyword.toLowerCase()));
- }else{
- query = SearchUtils.getBooleanQuery(field, keyword);
- }
- logger.info(query.toString());
- Sort sort = new Sort(new SortField(sortField, new StringFieldComparatorSource(keyword)));
- TopDocs hits = indexSearcher.search(query, size, sort);
- ScoreDoc[] scoreDocs = hits.scoreDocs;
- for (ScoreDoc scoreDoc : scoreDocs) {
- Set<String> fieldsToLoad = new HashSet<>();
- fieldsToLoad.add(field);
- Document document = indexSearcher.doc(scoreDoc.doc, fieldsToLoad);
- result.add(document.get(field));
- // System.out.println(document.get(field) + "\t" +
- // scoreDoc.score);
- }
- } catch (IOException e) {
- logger.error("", e);
- } finally {
- releaseIndexSearcher(indexSearcher);
- }
- return result;
- }
- /**
- * 移除集合中重复的元素
- *
- * @param list
- * @return
- */
- private void removeDuplicate(List<String> list) {
- if (list == null) {
- return;
- }
- List<String> result = new ArrayList<>();
- for (String str : list) {
- if (!result.contains(str)) {
- result.add(str);
- }
- }
- list.removeAll(list);
- list.addAll(result);
- }
- /**
- * 删除集合内 startIndex(含)后的元素
- *
- * @param list
- * @param startIndex
- */
- private void removeElements(List<? extends String> list, int startIndex) {
- if (CollectionUtils.isEmpty(list)) {
- return;
- }
- int listsSize = list.size();
- for (int i = listsSize - 1; i >= startIndex; i--) {
- list.remove(i);
- }
- }
- @Override
- public Map<String, Object> getGoodsIds(String keyword, PageParams pageParams) throws IOException {
- // List<String> keywordFields = new ArrayList<>();
- // 先根据品牌搜索,品牌不存在再搜索型号等
- // keywordFields.add(SearchConstants.GOODS_BR_NAME_CN_UNTOKENIZED_FIELD);
- // keywordFields.add(SearchConstants.GOODS_BR_NAME_EN_UNTOKENIZED_FIELD);
- // Map<String, Object> goodsIds = getGoodsIds(keyword, keywordFields, false, pageParams);
- // if (CollectionUtils.isEmpty(goodsIds) || goodsIds.get("componentIds") == null
- // || JSONObject.parseArray(goodsIds.get("componentIds").toString()).isEmpty()) {
- // keyword = recursivelyGetGoodsIds(keyword, null, true);
- // goodsIds = getGoodsIds(keyword, null, true, pageParams);
- // }
- // return goodsIds;
- Map<String, Object> map = new HashMap<>();
- List<String> goodsFields = new ArrayList<>();
- List<String> productsFields = new ArrayList<>();
- // 先根据品牌搜索,品牌不存在再搜索型号等
- goodsFields.add(GOODS_PR_PCMPCODE_FIELD);
- goodsFields.add(SearchConstants.GOODS_CMP_CODE_FIELD);
- productsFields.add(SearchConstants.PRODUCT_PRIVATE_CMPCODE_FIELD);
- productsFields.add(SearchConstants.PRODUCT_PRIVATE_PCMPCODE_FIELD);
- PageParams stockPageParams = new PageParams(pageParams);
- PageParams futuresPageParams = new PageParams(pageParams);
- String productkeyword = new String(keyword);
- // 现货
- Map<String, Object> stock = getGoodsIds(keyword, goodsFields, false, pageParams);
- // 如搜索无结果则分词
- if (CollectionUtils.isEmpty(stock) || stock.get("content") == null || JSONObject.parseArray(stock.get("content").toString()).isEmpty()) {
- keyword = recursivelyGetGoodsIds(keyword, goodsFields, true);
- stock = getGoodsIds(keyword, goodsFields, true, stockPageParams);
- }
- // 期货
- PageParams recursivelyPageParams = new PageParams(pageParams);
- SPage<Long> futures = getProductIds(productkeyword, productsFields, false, futuresPageParams);
- // 如搜索无结果则分词
- if (futures == null || CollectionUtils.isEmpty(futures.getContent())) {
- productkeyword = recursivelyProductIds(productkeyword, productsFields, true);
- futures = getProductIds(productkeyword, productsFields, true, recursivelyPageParams);
- }
- map.put("stock", stock);
- map.put("futures", futures);
- return map;
- }
- @Override
- public Map<String, Object> getOldGoodsIds(String keyword, PageParams pageParams) throws IOException {
- List<String> keywordFields = new ArrayList<>();
- // 先根据品牌搜索,品牌不存在再搜索型号等
- keywordFields.add(GOODS_BR_NAME_CN_UNTOKENIZED_FIELD);
- keywordFields.add(GOODS_BR_NAME_EN_UNTOKENIZED_FIELD);
- Map<String, Object> goodsIds = getOldGoodsIds(keyword, keywordFields, false, pageParams);
- if (CollectionUtils.isEmpty(goodsIds) || goodsIds.get("componentIds") == null
- || JSONObject.parseArray(goodsIds.get("componentIds").toString()).isEmpty()) {
- keyword = recursivelyGetGoodsIds(keyword, null, true);
- goodsIds = getOldGoodsIds(keyword, null, true, pageParams);
- }
- return goodsIds;
- }
- /**
- * 递归查询物料(如果没有结果,则降低精度,直至长度为 1)
- *
- * @param keyword 关键词
- * @param keywordFields 要查询的字段
- * @param tokenized 是否分词
- * @return 最后一次搜索的关键词
- */
- private String recursivelyProductIds(String keyword, List<String> keywordFields, Boolean tokenized) throws IOException {
- IndexSearcher indexSearcher = SearchUtils.getIndexSearcher(SearchConstants.PRODUCTS_PRIVATE_TABLE_NAME);
- try {
- BooleanQuery booleanQuery = queryProducts(keyword, keywordFields, tokenized);
- logger.info(booleanQuery.toString());
- TotalHitCountCollector collector = new TotalHitCountCollector();
- indexSearcher.search(booleanQuery, collector);
- // 如果没有结果,则降低精度,直至 keyword 长度为 1
- if (collector.getTotalHits() < 1 && !SearchUtils.isKeywordInvalid(keyword) && keyword.length() > 1) {
- return recursivelyProductIds(keyword.substring(0, keyword.length() - 1), keywordFields, tokenized);
- }
- return keyword;
- } finally {
- releaseIndexSearcher(indexSearcher);
- }
- }
- /**
- * 递归查询品牌(如果没有结果,则降低精度,直至长度为 1)
- *
- * @param keyword 关键词
- * @param keywordFields 要查询的字段
- * @param tokenized 是否分词
- * @return 最后一次搜索的关键词
- */
- private String recursivelyBrands(String keyword, List<String> keywordFields, Boolean tokenized) throws IOException {
- IndexSearcher indexSearcher = SearchUtils.getIndexSearcher(SearchConstants.BRAND_TABLE_NAME);
- try {
- BooleanQuery booleanQuery = queryBrands(keyword, keywordFields, tokenized);
- logger.info(booleanQuery.toString());
- TotalHitCountCollector collector = new TotalHitCountCollector();
- indexSearcher.search(booleanQuery, collector);
- // 如果没有结果,则降低精度,直至 keyword 长度为 1
- if (collector.getTotalHits() < 1 && !SearchUtils.isKeywordInvalid(keyword) && keyword.length() > 1) {
- return recursivelyBrands(keyword.substring(0, keyword.length() - 1), keywordFields, tokenized);
- }
- return keyword;
- } finally {
- releaseIndexSearcher(indexSearcher);
- }
- }
- /**
- * 通过递归类目查询物料(如果没有结果,则降低精度,直至长度为 1)
- *
- * @param keyword 关键词
- * @return 最后一次搜索的关键词
- */
- private String recursivelyKindsForSellers(String indexName, String keyword, Query query, String duplicateType) throws IOException {
- IndexSearcher indexSearcher = SearchUtils.getIndexSearcher(indexName);
- try {
- DuplicateFilter duplicateFilter = null;
- if (!StringUtils.isEmpty(duplicateType)) {
- if (duplicateType.equals(SearchConstants.BRAND)) {
- duplicateFilter = new DuplicateFilter(indexName.equals(SearchConstants.GOODS_TABLE_NAME) ? SearchConstants.GOODS_PR_PBRAND_EN_CN_STUUID_UNTOKENIZED_FIELD : SearchConstants.PRODUCT_PRIVATE_PBRAND_ENUU_FIELD);
- } else if (duplicateType.equals(SearchConstants.KIND)) {
- duplicateFilter = new DuplicateFilter(indexName.equals(SearchConstants.GOODS_TABLE_NAME) ? SearchConstants.GOODS_KIND_STUUID_UNTOKENIZED_FIELD : SearchConstants.PRODUCT_PRIVATE_KIND_ENUU_FIELD);
- }
- }
- TotalHitCountCollector collector = new TotalHitCountCollector();
- indexSearcher.search(query, duplicateFilter, collector);
- // 如果没有结果,则降低精度,直至 keyword 长度为 1
- if (collector.getTotalHits() < 1 && !SearchUtils.isKeywordInvalid(keyword) && keyword.length() > 1) {
- return recursivelyKindsForSellers(indexName, keyword.substring(0, keyword.length() - 1), query, duplicateType);
- }
- return keyword;
- } finally {
- releaseIndexSearcher(indexSearcher);
- }
- }
- /**
- * @param keyword
- * @param keywordFields
- * 要查询的字段
- * @param tokenized
- * 是否分词
- * @param pageParams
- * @return
- */
- private Map<String, Object> getGoodsIds(String keyword, List<String> keywordFields, Boolean tokenized,
- PageParams pageParams) {
- // 因为器件、属性值的数据量远比类目、品牌大得多,而且器件搜索可能还需进行分页,
- // 所以涉及器件、属性值的搜索,大都不能像类目和品牌一样直接利用SearchUtils.getDocuments方法
- IndexSearcher indexSearcher = SearchUtils.getIndexSearcher(SearchConstants.GOODS_TABLE_NAME);
- if (pageParams == null) {
- pageParams = new PageParams();
- }
- if (pageParams.getPage() <= 0)
- pageParams.setPage(1);
- if (pageParams.getSize() <= 0)
- pageParams.setSize(20);
- Map<String, Object> map = new HashMap<String, Object>();
- // List<Long> cmpIds = new ArrayList<>();
- List<Long> goIds = new ArrayList<>();
- try {
- BooleanQuery booleanQuery = queryGoods(keyword, keywordFields, tokenized);
- setGoodsFilter(pageParams.getFilters(), booleanQuery);
- logger.info(booleanQuery.toString());
- Sort sort = sortGoods(keyword, pageParams.getSort());
- TopDocs hits;
- if (pageParams.getPage() > 1) {// 不是第一页
- TopDocs previousHits = indexSearcher.search(booleanQuery, (pageParams.getPage() - 1) * pageParams.getSize(), sort, true, false);
- int totalHits = previousHits.totalHits;
- if (totalHits == 0) {
- return map;
- }
- int totalPage = (int) Math.ceil(totalHits / (1.0 * pageParams.getSize()));
- if (pageParams.getPage() > totalPage) {
- pageParams.setPage(totalPage);
- if (totalPage == 1) {
- hits = indexSearcher.search(booleanQuery, pageParams.getSize(), sort, true, false);
- } else {
- previousHits = indexSearcher.search(booleanQuery, (pageParams.getPage() - 1) * pageParams.getSize(), sort, true, false);
- ScoreDoc[] previousScoreDocs = previousHits.scoreDocs;
- ScoreDoc after = previousScoreDocs[previousScoreDocs.length - 1];
- hits = indexSearcher.searchAfter(after, booleanQuery, pageParams.getSize(), sort, true, false);
- }
- } else {
- ScoreDoc[] previousScoreDocs = previousHits.scoreDocs;
- ScoreDoc after = previousScoreDocs[previousScoreDocs.length - 1];
- hits = indexSearcher.searchAfter(after, booleanQuery, pageParams.getSize(), sort, true, false);
- }
- } else {
- hits = indexSearcher.search(booleanQuery, pageParams.getSize(), sort, true, false);
- }
- // 数据量太大,需要指定将获取的数据(以免载入不必要的数据,降低速度)
- Set<String> fieldsToLoad = new HashSet<>();
- // fieldsToLoad.add(SearchConstants.GOODS_CMP_ID_FIELD);
- fieldsToLoad.add(SearchConstants.GOODS_GO_ID_FIELD);
- ScoreDoc[] scoreDocs = hits.scoreDocs;
- int totalHits = hits.totalHits;
- for (ScoreDoc scoreDoc : scoreDocs) {
- Document document = indexSearcher.doc(scoreDoc.doc, fieldsToLoad);
- // String cmpId = document.get(SearchConstants.GOODS_CMP_ID_FIELD);
- // cmpIds.add(StringUtils.isEmpty(cmpId) || cmpId.equals(ObjectToDocumentUtils.NULL_VALUE) ? null : Long.valueOf(cmpId));
- String goId = document.get(SearchConstants.GOODS_GO_ID_FIELD);
- if (!StringUtils.isEmpty(goId) && !goId.equals(ObjectToDocumentUtils.NULL_VALUE)) {
- goIds.add(Long.valueOf(goId));
- } else {
- totalHits--;
- }
- }
- // map.put("componentIds", cmpIds);
- map.put("content", goIds);
- map.put("page", pageParams.getPage());
- map.put("size", pageParams.getSize());
- map.put("totalElement", totalHits);
- int totalPage = (int) Math.ceil(totalHits / (1.0 * pageParams.getSize()));
- map.put("totalPage", totalPage);
- map.put("last", totalPage == pageParams.getPage() ? true : false);
- map.put("first", pageParams.getPage() == 1 ? true : false);
- } catch (IOException e) {
- logger.error("", e);
- } finally {
- releaseIndexSearcher(indexSearcher);
- }
- return map;
- }
- /**
- * @param keyword
- * @param keywordFields
- * 要查询的字段
- * @param tokenized
- * 是否分词
- * @param pageParams
- * @return
- */
- private Map<String, Object> getOldGoodsIds(String keyword, List<String> keywordFields, Boolean tokenized,
- PageParams pageParams) {
- // 因为器件、属性值的数据量远比类目、品牌大得多,而且器件搜索可能还需进行分页,
- // 所以涉及器件、属性值的搜索,大都不能像类目和品牌一样直接利用SearchUtils.getDocuments方法
- IndexSearcher indexSearcher = SearchUtils.getIndexSearcher(SearchConstants.GOODS_TABLE_NAME);
- if (pageParams == null) {
- pageParams = new PageParams();
- }
- if (pageParams.getPage() <= 0)
- pageParams.setPage(1);
- if (pageParams.getSize() <= 0)
- pageParams.setSize(20);
- Map<String, Object> map = new HashMap<String, Object>();
- List<Long> cmpIds = new ArrayList<>();
- List<Long> goIds = new ArrayList<>();
- try {
- BooleanQuery booleanQuery = queryGoods(keyword, keywordFields, tokenized);
- setGoodsFilter(pageParams.getFilters(), booleanQuery);
- logger.info(booleanQuery.toString());
- Sort sort = sortGoods(keyword, pageParams.getSort());
- TopDocs hits;
- if (pageParams.getPage() > 1) {// 不是第一页
- TopDocs previousHits = indexSearcher.search(booleanQuery,
- (pageParams.getPage() - 1) * pageParams.getSize(), sort, true, false);
- int totalHits = previousHits.totalHits;
- if ((pageParams.getPage() - 1) * pageParams.getSize() >= totalHits) {
- return map;
- }
- ScoreDoc[] previousScoreDocs = previousHits.scoreDocs;
- ScoreDoc after = previousScoreDocs[previousScoreDocs.length - 1];
- hits = indexSearcher.searchAfter(after, booleanQuery, pageParams.getSize(), sort, true, false);
- } else {
- hits = indexSearcher.search(booleanQuery, pageParams.getSize(), sort, true, false);
- }
- // 数据量太大,需要指定将获取的数据(以免载入不必要的数据,降低速度)
- Set<String> fieldsToLoad = new HashSet<>();
- fieldsToLoad.add(SearchConstants.GOODS_CMP_ID_FIELD);
- fieldsToLoad.add(SearchConstants.GOODS_GO_ID_FIELD);
- ScoreDoc[] scoreDocs = hits.scoreDocs;
- for (ScoreDoc scoreDoc : scoreDocs) {
- Document document = indexSearcher.doc(scoreDoc.doc, fieldsToLoad);
- String cmpId = document.get(SearchConstants.GOODS_CMP_ID_FIELD);
- cmpIds.add(StringUtils.isEmpty(cmpId) || cmpId.equals(ObjectToDocumentUtils.NULL_VALUE) ? null : Long.valueOf(cmpId));
- String goId = document.get(SearchConstants.GOODS_GO_ID_FIELD);
- goIds.add(StringUtils.isEmpty(goId) || goId.equals(ObjectToDocumentUtils.NULL_VALUE) ? null : Long.valueOf(goId));
- }
- map.put("componentIds", cmpIds);
- map.put("goodsIds", goIds);
- map.put("page", pageParams.getPage());
- map.put("size", pageParams.getSize());
- map.put("total", hits.totalHits);
- } catch (IOException e) {
- logger.error("", e);
- } finally {
- SearchUtils.releaseIndexSearcher(indexSearcher);
- }
- return map;
- }
- /**
- * 获取物料信息
- * @param keyword
- * @return
- */
- private SPage<Long> getProductIds(String keyword, List<String> keywordFields, Boolean tokenized, PageParams pageParams) throws IOException{
- if (pageParams == null) {
- pageParams = new PageParams();
- }
- if (pageParams.getPage() <= 0)
- pageParams.setPage(1);
- if (pageParams.getSize() <= 0)
- pageParams.setSize(20);
- BooleanQuery booleanQuery = queryProducts(keyword, keywordFields, tokenized);
- logger.info(booleanQuery.toString());
- SPage<Document> documents = getDocuments(SearchConstants.PRODUCTS_PRIVATE_TABLE_NAME, booleanQuery, new Sort(sortProduct()), pageParams.getPage(), pageParams.getSize());
- SPage<Long> sPage = new SPage<>(documents.getTotalPage(), documents.getTotalElement(), documents.getPage(), documents.getSize(), documents.isFirst(), documents.isLast());
- List<Long> productIds = new ArrayList<>();
- for (Document document : documents.getContent()) {
- productIds.add(Long.parseLong(document.get(SearchConstants.PRODUCT_PRIVATE_ID_FIELD)));
- }
- sPage.setContent(productIds);
- return sPage;
- }
- /**
- * 递归查询批次(如果没有结果,则降低精度,直至长度为 1)
- *
- * @param keyword 关键词
- * @param keywordFields 要查询的字段
- * @param tokenized 是否分词
- * @return 最后一次搜索的关键词
- */
- private String recursivelyGetGoodsIds(String keyword, List<String> keywordFields, Boolean tokenized) throws IOException {
- IndexSearcher indexSearcher = SearchUtils.getIndexSearcher(SearchConstants.GOODS_TABLE_NAME);
- try {
- BooleanQuery booleanQuery = queryGoods(keyword, keywordFields, tokenized);
- logger.info(booleanQuery.toString());
- TotalHitCountCollector collector = new TotalHitCountCollector();
- indexSearcher.search(booleanQuery, collector);
- // 如果没有结果,则降低精度,直至 keyword 长度为 1
- if (collector.getTotalHits() < 1 && !SearchUtils.isKeywordInvalid(keyword) && keyword.length() > 1) {
- return recursivelyGetGoodsIds(keyword.substring(0, keyword.length() - 1), keywordFields, tokenized);
- }
- return keyword;
- } finally {
- releaseIndexSearcher(indexSearcher);
- }
- }
- /**
- * 设置批次过滤条件
- *
- * @param filters 指定的过滤条件
- * @param query 原查询
- */
- private void setGoodsFilter(Map<FilterField, Object> filters, BooleanQuery query) {
- Object status;
- // 筛选状态
- if (!CollectionUtils.isEmpty(filters) && !StringUtils.isEmpty(filters.get(FilterField.GOODS_STATUS))) {
- // 如果明确指定了状态,则直接过滤批次(结果中不包括没有批次的器件)
- status = filters.get(FilterField.GOODS_STATUS);
- filter(status, SearchConstants.GOODS_GO_STATUS_FIELD, query);
- } else {
- // 如果未明确指定状态,则使用默认状态分情况进行过滤(结果中包括没有批次的器件)
- status = Arrays.asList(TradeGoods.VALID_STATUS);
- // 批次 id 不为空时,对状态过滤
- Query goNullQuery = SearchUtils.getNullQuery(SearchConstants.GOODS_GO_ID_FIELD);
- BooleanQuery q1 = new BooleanQuery();
- q1.add(goNullQuery, Occur.MUST_NOT);
- filter(status, SearchConstants.GOODS_GO_STATUS_FIELD, q1);
- // 或者批次 id 为空(此时是器件)
- BooleanQuery q2 = new BooleanQuery();
- q2.add(SearchUtils.getNullQuery(SearchConstants.GOODS_CMP_ID_FIELD), Occur.MUST_NOT);
- q2.add(goNullQuery, Occur.MUST);
- BooleanQuery booleanQuery = new BooleanQuery();
- booleanQuery.add(q1, Occur.SHOULD);
- booleanQuery.add(q2, Occur.SHOULD);
- query.add(booleanQuery, Occur.FILTER);
- }
- if (CollectionUtils.isEmpty(filters)) {
- return;
- }
- // 筛选类目
- if (!StringUtils.isEmpty(filters.get(FilterField.GOODS_KINDID))) {
- filter(filters.get(FilterField.GOODS_KINDID), SearchConstants.GOODS_KI_ID_FIELD, query);
- }
- // 筛选品牌
- if (!StringUtils.isEmpty(filters.get(FilterField.GOODS_BRANDID))) {
- filter(filters.get(FilterField.GOODS_BRANDID), SearchConstants.GOODS_BR_ID_FIELD, query);
- }
- // 筛选货源
- if (!StringUtils.isEmpty(filters.get(FilterField.GOODS_STORE_TYPE))) {
- filter(filters.get(FilterField.GOODS_STORE_TYPE), SearchConstants.GOODS_ST_TYPE_FIELD, query);
- }
- // 筛选货币
- if (!StringUtils.isEmpty(filters.get(FilterField.GOODS_CRNAME))) {
- filter(filters.get(FilterField.GOODS_CRNAME), SearchConstants.GOODS_CRNAME_FIELD, query);
- }
- // 价格筛选
- Object minPriceRmb = filters.get(FilterField.GOODS_MINPRICERMB);
- Object maxPriceRmb = filters.get(FilterField.GOODS_MAXPRICERMB);
- Object minPriceUsd = filters.get(FilterField.GOODS_MINPRICEUSD);
- Object maxPriceUsd = filters.get(FilterField.GOODS_MAXPRICEUSD);
- // 筛选人民币价格
- if (!StringUtils.isEmpty(minPriceRmb) || !StringUtils.isEmpty(maxPriceRmb)) {
- Double minPrice = null;
- Double maxPrice = null;
- if (!StringUtils.isEmpty(minPriceRmb)) {
- minPrice = Double.valueOf(minPriceRmb.toString());
- }
- if (!StringUtils.isEmpty(maxPriceRmb)) {
- maxPrice = Double.valueOf(maxPriceRmb.toString());
- }
- query.add(NumericRangeQuery.newDoubleRange(SearchConstants.GOODS_GO_MINPRICERMB_FIELD,
- minPrice, maxPrice, true, true), BooleanClause.Occur.FILTER);
- }
- // 筛选美元价格
- if (!StringUtils.isEmpty(minPriceUsd) || !StringUtils.isEmpty(maxPriceUsd)) {
- Double minPrice = null;
- Double maxPrice = null;
- if (!StringUtils.isEmpty(minPriceUsd)) {
- minPrice = Double.valueOf(minPriceUsd.toString());
- }
- if (!StringUtils.isEmpty(maxPriceUsd)) {
- maxPrice = Double.valueOf(maxPriceUsd.toString());
- }
- query.add(NumericRangeQuery.newDoubleRange(SearchConstants.GOODS_GO_MINPRICEUSD_FIELD,
- minPrice, maxPrice, true, true), BooleanClause.Occur.FILTER);
- }
- }
- /**
- * 设置批次过滤条件
- *
- * @param filters 指定的过滤条件
- * @param query 原查询
- */
- private void setProductsFilter(Map<FilterField, Object> filters, BooleanQuery query) {
- Object status;
- // 筛选状态
- if (!CollectionUtils.isEmpty(filters) && !StringUtils.isEmpty(filters.get(FilterField.PRODUCT_STATUS))) {
- // 如果明确指定了状态,则直接过滤物料
- status = filters.get(FilterField.PRODUCT_STATUS);
- filter(status, SearchConstants.PRODUCT_PRIVATE_B2CENABLED_FIELD, query);
- } else {
- // 如果未明确指定状态,则使用默认状态分情况进行过滤(结果中包括没有批次的器件)
- status = Arrays.asList(V_Products.VALID_STATUS);
- // 或者批次 id 为空(此时是器件)
- BooleanQuery q2 = new BooleanQuery();
- BooleanQuery booleanQuery = new BooleanQuery();
- booleanQuery.add(q2, Occur.SHOULD);
- query.add(booleanQuery, Occur.FILTER);
- }
- }
- /**
- * 批次排序规则
- */
- private Sort sortGoods(String keyword, com.uas.search.constant.model.Sort sort) {
- List<SortField> sortFieldList = new ArrayList<>();
- sortFieldList.add(SortField.FIELD_SCORE);
- if (sort != null) {
- com.uas.search.constant.model.Sort.Field field = sort.getField();
- if (field == null) {
- throw new IllegalArgumentException("排序字段不可为空:" + sort);
- }
- boolean reverse = sort.isReverse();
- if (field == RESERVE) {
- // 库存
- sortFieldList.addAll(Arrays.asList(
- // 降序时,默认值为最小值;升序时,默认值为最大值
- sortField(SearchConstants.GOODS_GO_RESERVE_FIELD, Type.DOUBLE, reverse, reverse ? Double.MIN_VALUE : Double.MAX_VALUE),
- sortField(SearchConstants.GOODS_CMP_WEIGHT_FIELD, Type.DOUBLE, true, Double.MIN_VALUE),
- sortField(SearchConstants.GOODS_BR_WEIGHT_FIELD, Type.DOUBLE, true, Double.MIN_VALUE),
- sortField(SearchConstants.GOODS_GO_MINPRICERMB_FIELD, Type.DOUBLE, false, Double.MAX_VALUE),
- sortField(SearchConstants.GOODS_GO_MINPRICEUSD_FIELD, Type.DOUBLE, false, Double.MAX_VALUE)
- ));
- } else if (field == PRICE) {
- // 价格
- sortFieldList.addAll(Arrays.asList(
- // 降序时,默认值为最小值;升序时,默认值为最大值
- sortField(SearchConstants.GOODS_GO_MINPRICERMB_FIELD, Type.DOUBLE, reverse, reverse ? Double.MIN_VALUE : Double.MAX_VALUE),
- sortField(SearchConstants.GOODS_GO_MINPRICEUSD_FIELD, Type.DOUBLE, reverse, reverse ? Double.MIN_VALUE : Double.MAX_VALUE),
- sortField(SearchConstants.GOODS_CMP_WEIGHT_FIELD, Type.DOUBLE, true, Double.MIN_VALUE),
- sortField(SearchConstants.GOODS_BR_WEIGHT_FIELD, Type.DOUBLE, true, Double.MIN_VALUE),
- sortField(SearchConstants.GOODS_GO_RESERVE_FIELD, Type.DOUBLE, true, Double.MIN_VALUE)
- ));
- } else {
- throw new IllegalArgumentException("不支持该排序方式:" + field);
- }
- } else {
- // 默认(综合排序)
- sortFieldList.addAll(Arrays.asList(
- sortField(SearchConstants.GOODS_CMP_WEIGHT_FIELD, Type.DOUBLE, true, Double.MIN_VALUE),
- sortField(SearchConstants.GOODS_BR_WEIGHT_FIELD, Type.DOUBLE, true, Double.MIN_VALUE),
- sortField(SearchConstants.GOODS_GO_MINPRICERMB_FIELD, Type.DOUBLE, false, Double.MAX_VALUE),
- sortField(SearchConstants.GOODS_GO_MINPRICEUSD_FIELD, Type.DOUBLE, false, Double.MAX_VALUE),
- sortField(SearchConstants.GOODS_GO_RESERVE_FIELD, Type.DOUBLE, true, Double.MIN_VALUE),
- sortField(SearchConstants.GOODS_GO_MINDELIVERY_FIELD, Type.LONG, false, Long.MAX_VALUE)
- ));
- }
- sortFieldList.addAll(Arrays.asList(
- // 如果仍然无法得到正确结果,就根据按照型号等顺序严格排列
- // new SortField(SearchConstants.GOODS_CMP_CODE_FIELD, new StringFieldComparatorSource(keyword, false)),
- new SortField(GOODS_PR_PCMPCODE_FIELD, new StringFieldComparatorSource(keyword, false)),
- new SortField(GOODS_BR_NAME_EN_UNTOKENIZED_FIELD, new StringFieldComparatorSource(keyword, false)),
- new SortField(GOODS_BR_NAME_CN_UNTOKENIZED_FIELD, new StringFieldComparatorSource(keyword, false)),
- new SortField(SearchConstants.GOODS_PR_KIND_FIELD, new StringFieldComparatorSource(keyword, false)),
- new SortField(SearchConstants.GOODS_CMP_CODE_FIELD, new StringFieldComparatorSource(keyword, false)),
- // new SortField(SearchConstants.GOODS_KI_NAME_CN_UNTOKENIZED_FIELD, new StringFieldComparatorSource(keyword, false)),
- new SortField(SearchConstants.GOODS_GO_ATTACH_FIELD, Type.DOUBLE, true),
- sortField(SearchConstants.GOODS_GO_UPDATE_DATE_FIELD, Type.LONG, true, Long.MIN_VALUE)
- ));
- SortField[] sortFields = new SortField[sortFieldList.size()];
- sortFieldList.toArray(sortFields);
- return new Sort(sortFields);
- }
- @Override
- public Map<String, Object> getPCBGoodsIds(String keyword, PageParams pageParams) throws IOException {
- keyword = recursivelyGetPCBGoodsIds(keyword);
- // 因为器件、属性值等的数据量远比类目、品牌大得多,而且器件搜索可能还需进行分页,
- // 所以涉及器件、属性值的搜索,大都不能像类目和品牌一样直接利用SearchUtils.getDocuments方法
- IndexSearcher indexSearcher = SearchUtils.getIndexSearcher(SearchConstants.PCB_GOODS_TABLE_NAME);
- if (pageParams == null) {
- pageParams = new PageParams();
- }
- if (pageParams.getPage() <= 0)
- pageParams.setPage(1);
- if (pageParams.getSize() <= 0)
- pageParams.setSize(20);
- Map<String, Object> map = new HashMap<String, Object>();
- List<Long> pcbIds = new ArrayList<>();
- List<Long> goIds = new ArrayList<>();
- try {
- BooleanQuery booleanQuery = queryPCBGoods(keyword);
- setPCBGoodsFilter(pageParams.getFilters(), booleanQuery);
- logger.info(booleanQuery.toString());
- Sort sort = sortPCBGoods(keyword, pageParams.getSort());
- TopDocs hits;
- if (pageParams.getPage() > 1) { // 不是第一页
- TopDocs previousHits = indexSearcher.search(booleanQuery,
- (pageParams.getPage() - 1) * pageParams.getSize(), sort, true, false);
- int totalHits = previousHits.totalHits;
- if ((pageParams.getPage() - 1) * pageParams.getSize() >= totalHits) {
- return map;
- }
- ScoreDoc[] previousScoreDocs = previousHits.scoreDocs;
- ScoreDoc after = previousScoreDocs[previousScoreDocs.length - 1];
- hits = indexSearcher.searchAfter(after, booleanQuery, pageParams.getSize(), sort, true, false);
- } else {
- hits = indexSearcher.search(booleanQuery, pageParams.getSize(), sort, true, false);
- }
- // 数据量太大,需要指定将获取的数据(以免载入不必要的数据,降低速度)
- Set<String> fieldsToLoad = new HashSet<>();
- fieldsToLoad.add(SearchConstants.PCB_GOODS_PCB_ID_FIELD);
- fieldsToLoad.add(SearchConstants.PCB_GOODS_GO_ID_FIELD);
- ScoreDoc[] scoreDocs = hits.scoreDocs;
- for (ScoreDoc scoreDoc : scoreDocs) {
- Document document = indexSearcher.doc(scoreDoc.doc, fieldsToLoad);
- String pcbId = document.get(SearchConstants.PCB_GOODS_PCB_ID_FIELD);
- pcbIds.add(StringUtils.isEmpty(pcbId) || pcbId.equals(ObjectToDocumentUtils.NULL_VALUE) ? null : Long.valueOf(pcbId));
- String goId = document.get(SearchConstants.PCB_GOODS_GO_ID_FIELD);
- goIds.add(StringUtils.isEmpty(goId) || goId.equals(ObjectToDocumentUtils.NULL_VALUE) ? null : Long.valueOf(goId));
- }
- map.put("pcbIds", pcbIds);
- map.put("goodsIds", goIds);
- map.put("page", pageParams.getPage());
- map.put("size", pageParams.getSize());
- map.put("total", hits.totalHits);
- } catch (IOException e) {
- logger.error("", e);
- } finally {
- releaseIndexSearcher(indexSearcher);
- }
- return map;
- }
- /**
- * 递归查询 PCB 批次(如果没有结果,则降低精度,直至长度为 1)
- *
- * @param keyword 关键词
- * @return 最后一次搜索的关键词
- */
- private String recursivelyGetPCBGoodsIds(String keyword) throws IOException {
- IndexSearcher indexSearcher = SearchUtils.getIndexSearcher(SearchConstants.PCB_GOODS_TABLE_NAME);
- try {
- BooleanQuery booleanQuery = queryPCBGoods(keyword);
- logger.info(booleanQuery.toString());
- TotalHitCountCollector collector = new TotalHitCountCollector();
- indexSearcher.search(booleanQuery, collector);
- // 如果没有结果,则降低精度,直至 keyword 长度为 1
- if (collector.getTotalHits() < 1 && !SearchUtils.isKeywordInvalid(keyword) && keyword.length() > 1) {
- return recursivelyGetPCBGoodsIds(keyword.substring(0, keyword.length() - 1));
- }
- return keyword;
- } finally {
- releaseIndexSearcher(indexSearcher);
- }
- }
- /**
- * 设置 PCB 批次过滤条件
- *
- * @param filters 指定的过滤条件
- * @param query 原查询
- */
- private void setPCBGoodsFilter(Map<FilterField, Object> filters, BooleanQuery query) {
- Object status;
- // 筛选状态
- if (!CollectionUtils.isEmpty(filters) && !StringUtils.isEmpty(filters.get(FilterField.GOODS_STATUS))) {
- // 如果明确指定了状态,则直接过滤批次(结果中不包括没有批次的 PCB)
- status = filters.get(FilterField.GOODS_STATUS);
- filter(status, SearchConstants.PCB_GOODS_GO_STATUS_FIELD, query);
- } else {
- // 如果未明确指定状态,则使用默认状态分情况进行过滤(结果中包括没有批次的 PCB)
- status = Arrays.asList(TradeGoods.VALID_STATUS);
- // 批次 id 不为空时,对状态过滤
- Query goNullQuery = SearchUtils.getNullQuery(SearchConstants.PCB_GOODS_GO_ID_FIELD);
- BooleanQuery q1 = new BooleanQuery();
- q1.add(goNullQuery, Occur.MUST_NOT);
- filter(status, SearchConstants.PCB_GOODS_GO_STATUS_FIELD, q1);
- // 或者批次 id 为空(此时是PCB)
- BooleanQuery q2 = new BooleanQuery();
- q2.add(SearchUtils.getNullQuery(SearchConstants.PCB_GOODS_PCB_ID_FIELD), Occur.MUST_NOT);
- q2.add(goNullQuery, Occur.MUST);
- BooleanQuery booleanQuery = new BooleanQuery();
- booleanQuery.add(q1, Occur.SHOULD);
- booleanQuery.add(q2, Occur.SHOULD);
- query.add(booleanQuery, Occur.FILTER);
- }
- if (CollectionUtils.isEmpty(filters)) {
- return;
- }
- // 筛选类目
- if (!StringUtils.isEmpty(filters.get(FilterField.GOODS_KINDID))) {
- filter(filters.get(FilterField.GOODS_KINDID), SearchConstants.PCB_GOODS_KI_ID_FIELD, query);
- }
- // 筛选品牌
- if (!StringUtils.isEmpty(filters.get(FilterField.GOODS_BRANDID))) {
- filter(filters.get(FilterField.GOODS_BRANDID), SearchConstants.PCB_GOODS_BR_ID_FIELD, query);
- }
- // 筛选货币
- if (!StringUtils.isEmpty(filters.get(FilterField.GOODS_CRNAME))) {
- filter(filters.get(FilterField.GOODS_CRNAME), SearchConstants.PCB_GOODS_CRNAME_FIELD, query);
- }
- // 价格筛选
- Object minPriceRmb = filters.get(FilterField.GOODS_MINPRICERMB);
- Object maxPriceRmb = filters.get(FilterField.GOODS_MAXPRICERMB);
- Object minPriceUsd = filters.get(FilterField.GOODS_MINPRICEUSD);
- Object maxPriceUsd = filters.get(FilterField.GOODS_MAXPRICEUSD);
- // 筛选人民币价格
- if (!StringUtils.isEmpty(minPriceRmb) || !StringUtils.isEmpty(maxPriceRmb)) {
- Double minPrice = null;
- Double maxPrice = null;
- if (!StringUtils.isEmpty(minPriceRmb)) {
- minPrice = Double.valueOf(minPriceRmb.toString());
- }
- if (!StringUtils.isEmpty(maxPriceRmb)) {
- maxPrice = Double.valueOf(maxPriceRmb.toString());
- }
- query.add(NumericRangeQuery.newDoubleRange(SearchConstants.PCB_GOODS_GO_MINPRICERMB_FIELD,
- minPrice, maxPrice, true, true), BooleanClause.Occur.FILTER);
- }
- // 筛选美元价格
- if (!StringUtils.isEmpty(minPriceUsd) || !StringUtils.isEmpty(maxPriceUsd)) {
- Double minPrice = null;
- Double maxPrice = null;
- if (!StringUtils.isEmpty(minPriceUsd)) {
- minPrice = Double.valueOf(minPriceUsd.toString());
- }
- if (!StringUtils.isEmpty(maxPriceUsd)) {
- maxPrice = Double.valueOf(maxPriceUsd.toString());
- }
- query.add(NumericRangeQuery.newDoubleRange(SearchConstants.PCB_GOODS_GO_MINPRICEUSD_FIELD,
- minPrice, maxPrice, true, true), BooleanClause.Occur.FILTER);
- }
- }
- /**
- * PCB 批次排序规则
- */
- private Sort sortPCBGoods(String keyword, com.uas.search.constant.model.Sort sort) {
- List<SortField> sortFieldList = new ArrayList<>();
- sortFieldList.add(SortField.FIELD_SCORE);
- if (sort != null) {
- com.uas.search.constant.model.Sort.Field field = sort.getField();
- if (field == null) {
- throw new IllegalArgumentException("排序字段不可为空:" + sort);
- }
- boolean reverse = sort.isReverse();
- if (field == RESERVE) {
- // 库存
- sortFieldList.addAll(Arrays.asList(
- // 降序时,默认值为最小值;升序时,默认值为最大值
- sortField(SearchConstants.PCB_GOODS_GO_RESERVE_FIELD, Type.DOUBLE, reverse, reverse ? Double.MIN_VALUE : Double.MAX_VALUE),
- sortField(SearchConstants.PCB_GOODS_GO_MINPRICERMB_FIELD, Type.DOUBLE, false, Double.MAX_VALUE),
- sortField(SearchConstants.PCB_GOODS_GO_MINPRICEUSD_FIELD, Type.DOUBLE, false, Double.MAX_VALUE)
- ));
- } else if (field == PRICE) {
- // 价格
- sortFieldList.addAll(Arrays.asList(
- // 降序时,默认值为最小值;升序时,默认值为最大值
- sortField(SearchConstants.PCB_GOODS_GO_MINPRICERMB_FIELD, Type.DOUBLE, reverse, reverse ? Double.MIN_VALUE : Double.MAX_VALUE),
- sortField(SearchConstants.PCB_GOODS_GO_MINPRICEUSD_FIELD, Type.DOUBLE, reverse, reverse ? Double.MIN_VALUE : Double.MAX_VALUE),
- sortField(SearchConstants.PCB_GOODS_GO_RESERVE_FIELD, Type.DOUBLE, true, Double.MIN_VALUE)
- ));
- } else {
- throw new IllegalArgumentException("不支持该排序方式:" + field);
- }
- } else {
- // 默认(综合排序)
- sortFieldList.addAll(Arrays.asList(
- sortField(SearchConstants.PCB_GOODS_GO_MINPRICERMB_FIELD, Type.DOUBLE, false, Double.MAX_VALUE),
- sortField(SearchConstants.PCB_GOODS_GO_MINPRICEUSD_FIELD, Type.DOUBLE, false, Double.MAX_VALUE),
- sortField(SearchConstants.PCB_GOODS_GO_RESERVE_FIELD, Type.DOUBLE, true, Double.MIN_VALUE),
- sortField(SearchConstants.PCB_GOODS_GO_MINDELIVERY_FIELD, Type.LONG, false, Long.MAX_VALUE)
- ));
- }
- sortFieldList.addAll(Arrays.asList(
- // 如果仍然无法得到正确结果,就根据按照型号等顺序严格排列
- new SortField(SearchConstants.PCB_GOODS_PR_PCMPCODE_FIELD, new StringFieldComparatorSource(keyword, false)),
- new SortField(SearchConstants.PCB_GOODS_BR_NAME_EN_UNTOKENIZED_FIELD, new StringFieldComparatorSource(keyword, false)),
- new SortField(SearchConstants.PCB_GOODS_BR_NAME_CN_UNTOKENIZED_FIELD, new StringFieldComparatorSource(keyword, false)),
- new SortField(SearchConstants.PCB_GOODS_KI_NAME_CN_UNTOKENIZED_FIELD, new StringFieldComparatorSource(keyword, false)),
- sortField(SearchConstants.PCB_GOODS_GO_UPDATE_DATE_FIELD, Type.LONG, true, Long.MIN_VALUE)
- ));
- SortField[] sortFields = new SortField[sortFieldList.size()];
- sortFieldList.toArray(sortFields);
- return new Sort(sortFields);
- }
- @Override
- public List<Map<String, Object>> collectBySearchGoods(String keyword, CollectField collectedField,
- Map<FilterField, Object> filters) throws IOException {
- List<String> keywordFields = new ArrayList<>();
- // 先根据品牌搜索,品牌不存在再搜索型号等
- keywordFields.add(GOODS_BR_NAME_CN_UNTOKENIZED_FIELD);
- keywordFields.add(GOODS_BR_NAME_EN_UNTOKENIZED_FIELD);
- List<Map<String, Object>> result = collectBySearchGoods(keyword, keywordFields, false, collectedField, filters);
- if (CollectionUtils.isEmpty(result)) {
- keyword = recursivelyGetGoodsIds(keyword, null, true);
- result = collectBySearchGoods(keyword, null, true, collectedField, filters);
- }
- return result;
- }
- /**
- * 获取卖家信息
- * @param keyword 关键词
- * @param keywordFields 搜索字段
- * @param page 页码
- * @param size 页数
- * @param tokenized 是否分词
- * @param duplicate 去重类型
- * @return
- */
- private Map<String, SPage<Object>> querySellers(String keyword, Map<String, List<String>> keywordFields, Integer page, Integer size, boolean tokenized, String duplicate) throws IOException {
- if (SearchUtils.isKeywordInvalid(keyword)) {
- throw new IllegalArgumentException("搜索关键词无效:" + keyword);
- }
- Map<String, SPage<Object>> map = new HashMap<>();
- // TODO 卖家排序
- Sort sort = null;
- // 未指定搜索的字段,则采用默认搜索逻辑
- if (CollectionUtils.isEmpty(keywordFields)) {
- Map<String, Query> boostQuerys = setSellersBoost(keyword);
- } else {
- Map<String, BooleanQuery> queryMap = queryKindForSellers(keyword, keywordFields, tokenized);
- BooleanQuery goodsQuery = queryMap.get("goodsQuery");
- BooleanQuery productsQuery = queryMap.get("productsQuery");
- // 现货卖家
- SPage<Object> stock = querySellers(SearchConstants.GOODS_TABLE_NAME, page, size, goodsQuery, sort, duplicate);
- if (duplicate.equals(SearchConstants.KIND) && (stock == null || CollectionUtils.isEmpty(stock.getContent()))) {
- keyword = recursivelyKindsForSellers(SearchConstants.GOODS_TABLE_NAME, keyword, goodsQuery, duplicate);
- goodsQuery = queryKindForSellers(keyword, keywordFields, tokenized).get("goodsQuery");
- stock = querySellers(SearchConstants.GOODS_TABLE_NAME, page, size, goodsQuery, sort, duplicate);
- }
- map.put("stock", stock);
- logger.info(goodsQuery.toString());
- // 期货卖家
- SPage<Object> futures = querySellers(SearchConstants.PRODUCTS_PRIVATE_TABLE_NAME, page, size, productsQuery, sort, duplicate);
- if (duplicate.equals(SearchConstants.KIND) && (futures == null || CollectionUtils.isEmpty(futures.getContent()))) {
- keyword = recursivelyKindsForSellers(SearchConstants.PRODUCTS_PRIVATE_TABLE_NAME, keyword, productsQuery, duplicate);
- productsQuery = queryKindForSellers(keyword, keywordFields, tokenized).get("productsQuery");
- futures = querySellers(SearchConstants.PRODUCTS_PRIVATE_TABLE_NAME, page, size, productsQuery, sort, duplicate);
- }
- map.put("futures", futures);
- logger.info(productsQuery.toString());
- }
- return map;
- }
- private Map<String, BooleanQuery> queryKindForSellers(String keyword, Map<String, List<String>> keywordFields, boolean tokenized) {
- Map<String, BooleanQuery> booleanQueryMap = new HashMap<>();
- BooleanQuery goodsQuery = new BooleanQuery();
- BooleanQuery productsQuery = new BooleanQuery();
- BooleanQuery goodsBooleanQuery = new BooleanQuery();
- BooleanQuery productsBooleanQuery = new BooleanQuery();
- for (String keywordField : keywordFields.get("goods")) {
- if (!tokenized) {
- goodsBooleanQuery.add(new TermQuery(new Term(keywordField, keyword.toLowerCase())), BooleanClause.Occur.SHOULD);
- } else {
- goodsBooleanQuery.add(SearchUtils.getBooleanQuery(keywordField, keyword), BooleanClause.Occur.SHOULD);
- }
- goodsQuery.add(goodsBooleanQuery, Occur.MUST);
- }
- for (String keywordField : keywordFields.get("products")) {
- if (!tokenized) {
- productsBooleanQuery.add(new TermQuery(new Term(keywordField, keyword.toLowerCase())), BooleanClause.Occur.SHOULD);
- } else {
- productsBooleanQuery.add(SearchUtils.getBooleanQuery(keywordField, keyword.toLowerCase()), BooleanClause.Occur.SHOULD);
- }
- productsQuery.add(productsBooleanQuery, Occur.MUST);
- }
- booleanQueryMap.put("goodsQuery", goodsQuery);
- booleanQueryMap.put("productsQuery", productsQuery);
- return booleanQueryMap;
- }
- private SPage<Object> querySellers(String indexName, Integer page, Integer size, BooleanQuery query, Sort sort, String duplicateType) throws IOException {
- SPage<Object> sPage = new SPage<>();
- if (page != null && page > 0) {
- sPage.setPage(page);
- } else {
- sPage.setPage(PAGE_INDEX);
- sPage.setFirst(true);
- }
- size = size != null && size > 0 ? size : PAGE_SIZE;
- sPage.setSize(size);
- DuplicateFilter duplicateFilter = null;
- if (!StringUtils.isEmpty(duplicateType)) {
- if (duplicateType.equals(SearchConstants.BRAND)) {
- duplicateFilter = new DuplicateFilter(indexName.equals(SearchConstants.GOODS_TABLE_NAME) ? SearchConstants.GOODS_PR_PBRAND_EN_CN_STUUID_UNTOKENIZED_FIELD : SearchConstants.PRODUCT_PRIVATE_PBRAND_ENUU_FIELD);
- } else if (duplicateType.equals(SearchConstants.KIND)) {
- duplicateFilter = new DuplicateFilter(indexName.equals(SearchConstants.GOODS_TABLE_NAME) ? SearchConstants.GOODS_KIND_STUUID_UNTOKENIZED_FIELD : SearchConstants.PRODUCT_PRIVATE_KIND_ENUU_FIELD);
- }
- }
- if (indexName.equals(SearchConstants.GOODS_TABLE_NAME)) {
- Object status = Arrays.asList(TradeGoods.VALID_STATUS);
- // 批次 id 不为空时,对状态过滤
- filter(status, SearchConstants.GOODS_GO_STATUS_FIELD, query);
- } else if (indexName.equals(SearchConstants.PRODUCTS_PRIVATE_TABLE_NAME)) {
- Object status = Arrays.asList(V_Products.VALID_STATUS);
- // 批次 id 不为空时,对状态过滤
- filter(status, SearchConstants.PRODUCT_PRIVATE_B2CENABLED_FIELD, query);
- }
- IndexSearcher indexSearcher = SearchUtils.getIndexSearcher(indexName);
- TopDocs topDocs;
- try {
- if (sort == null) {
- topDocs = duplicateFilter == null ? indexSearcher.search(query, DUPLICATE_PAGE_SIZE) : indexSearcher.search(query, duplicateFilter, DUPLICATE_PAGE_SIZE);
- } else {
- topDocs = duplicateFilter == null ? indexSearcher.search(query, DUPLICATE_PAGE_SIZE, sort) : indexSearcher.search(query, duplicateFilter, DUPLICATE_PAGE_SIZE, sort);
- }
- int totalHits = topDocs.totalHits;
- List<Document> documents = new ArrayList<>();
- for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
- documents.add(indexSearcher.doc(scoreDoc.doc));
- }
- List<Object> content = new ArrayList<>();
- List<Object> results = new ArrayList<>();
- if (indexName.equals(SearchConstants.GOODS_TABLE_NAME)) {
- for (Document document : documents) {
- results.add(document.get(SearchConstants.GOODS_ST_UUID_FIELD));
- }
- } else if (indexName.equals(SearchConstants.PRODUCTS_PRIVATE_TABLE_NAME)) {
- for (Document document : documents) {
- results.add(Long.parseLong(document.get(SearchConstants.PRODUCT_PRIVATE_ENUU_FIELD)));
- }
- }
- Map<String, List<Object>> map = new HashMap<>();
- // 结果去重
- for (Object object : results) {
- if (map.get(String.valueOf(object)) == null) {
- List<Object> storeUuids = new ArrayList<>();
- storeUuids.add(String.valueOf(object));
- map.put(String.valueOf(object), storeUuids);
- } else {
- map.get(String.valueOf(object)).add(object);
- totalHits --;
- }
- }
- // 按批次、物料数量排序
- List<Map.Entry<String, List<Object>>> stuuids = new ArrayList<>(map.entrySet());
- Collections.sort(stuuids, new Comparator<Map.Entry<String, List<Object>>> () {
- @Override
- public int compare(Map.Entry<String, List<Object>> o1, Map.Entry<String, List<Object>> o2) {
- return o1.getValue().size() - o2.getValue().size();
- }
- });
- // 设置总元素个数、页数等信息
- int totalPage = (int) Math.ceil(totalHits / (1.0 * sPage.getSize()));
- sPage.setTotalPage(totalPage);
- int filterPage = sPage.getPage() < totalPage ? sPage.getPage() : totalPage;
- sPage.setPage(filterPage);
- if (!CollectionUtils.isEmpty(stuuids)) {
- for (int i = (filterPage - 1) * size; i < (((filterPage - 1) * size + size > stuuids.size()) ? stuuids.size() : ((filterPage - 1) * size + size)); i ++) {
- content.add(stuuids.get(i).getKey());
- }
- }
- if (totalPage == sPage.getPage()) {
- sPage.setLast(true);
- }
- sPage.setSize(size);
- sPage.setTotalElement(totalHits);
- sPage.setContent(content);
- } finally {
- releaseIndexSearcher(indexSearcher);
- }
- return sPage;
- }
- private Map<String, Query> setSellersBoost(String keyword) {
- // TODO
- Map<String, Query> queryMap = new HashMap<>();
- BooleanQuery goodsQuery = new BooleanQuery();
- BooleanQuery productsQuery = new BooleanQuery();
- return null;
- }
- private SortField[] sortSellers(String keyword) {
- // TODO
- return null;
- }
- /**
- * @param keyword
- * @param keywordFields
- * 要查询的字段
- * @param tokenized
- * 是否分词
- * @param collectedField
- * @param filters
- * @return
- */
- private List<Map<String, Object>> collectBySearchGoods(String keyword, List<String> keywordFields,
- Boolean tokenized, CollectField collectedField, Map<FilterField, Object> filters) {
- if (collectedField == null) {
- throw new IllegalArgumentException("参数为空:collectedField");
- }
- IndexSearcher indexSearcher = SearchUtils.getIndexSearcher(SearchConstants.GOODS_TABLE_NAME);
- List<Map<String, Object>> result = new ArrayList<>();
- try {
- BooleanQuery booleanQuery = queryGoods(keyword, keywordFields, tokenized);
- setGoodsFilter(filters, booleanQuery);
- logger.info(booleanQuery.toString());
- // 统计
- String uniqueField;
- Set<String> fieldsToLoad = new HashSet<>();
- switch (collectedField) {
- case GOODS_KIND:
- uniqueField = SearchConstants.GOODS_KI_ID_FIELD;
- fieldsToLoad.add(SearchConstants.GOODS_KI_ID_FIELD);
- fieldsToLoad.add(GOODS_KI_NAME_CN_FIELD);
- break;
- case GOODS_BRAND:
- uniqueField = SearchConstants.GOODS_BR_ID_FIELD;
- fieldsToLoad.add(SearchConstants.GOODS_BR_ID_FIELD);
- fieldsToLoad.add(SearchConstants.GOODS_BR_UUID_FIELD);
- fieldsToLoad.add(GOODS_BR_NAME_CN_FIELD);
- fieldsToLoad.add(GOODS_BR_NAME_EN_FIELD);
- break;
- case GOODS_STORE_TYPE:
- uniqueField = SearchConstants.GOODS_ST_TYPE_FIELD;
- fieldsToLoad.add(SearchConstants.GOODS_ST_TYPE_FIELD);
- break;
- case GOODS_CRNAME:
- uniqueField = SearchConstants.GOODS_CRNAME_FIELD;
- fieldsToLoad.add(SearchConstants.GOODS_CRNAME_FIELD);
- break;
- default:
- throw new IllegalArgumentException("不支持该统计字段:" + collectedField);
- }
- GoodsGroupCollector collector = new GoodsGroupCollector(uniqueField, fieldsToLoad);
- indexSearcher.search(booleanQuery, collector);
- result = collector.getValues();
- } catch (IOException e) {
- logger.error("", e);
- } finally {
- releaseIndexSearcher(indexSearcher);
- }
- return result;
- }
- /**
- * 获取查询批次的query
- *
- * @param keyword
- * @param keywordFields
- * @param tokenized
- * @return
- */
- private BooleanQuery queryGoods(String keyword, List<String> keywordFields, Boolean tokenized) {
- BooleanQuery booleanQuery = new BooleanQuery();
- Query goNullQuery = SearchUtils.getNullQuery(SearchConstants.GOODS_GO_ID_FIELD);
- booleanQuery.add(goNullQuery, Occur.MUST_NOT);
- if (!SearchUtils.isKeywordInvalid(keyword)) {
- // 未指定搜索的字段,则采用默认搜索逻辑
- if (CollectionUtils.isEmpty(keywordFields)) {
- booleanQuery.add(setGoodsBoost(keyword), BooleanClause.Occur.MUST);
- } else {
- BooleanQuery booleanQuery2 = new BooleanQuery();
- for (String keywordField : keywordFields) {
- // 是否分词
- if (tokenized == null || !tokenized.booleanValue()) {
- booleanQuery2.add(new TermQuery(new Term(keywordField, keyword.toLowerCase())), BooleanClause.Occur.SHOULD);
- } else {
- booleanQuery2.add(SearchUtils.getBooleanQuery(keywordField, keyword), BooleanClause.Occur.SHOULD);
- }
- }
- booleanQuery.add(booleanQuery2, BooleanClause.Occur.MUST);
- }
- }
- return booleanQuery;
- }
- private BooleanQuery queryProducts(String keyword, List<String> keywordFields, Boolean tokenized) {
- BooleanQuery booleanQuery = new BooleanQuery();
- BooleanQuery q1 = new BooleanQuery();
- q1.add(new TermQuery(new Term(SearchConstants.PRODUCT_PRIVATE_B2CENABLED_FIELD, String.valueOf(1))), BooleanClause.Occur.MUST);
- booleanQuery.add(q1, BooleanClause.Occur.MUST);
- if (!SearchUtils.isKeywordInvalid(keyword)) {
- // 未指定搜索的字段,则采用默认搜索逻辑
- if (!CollectionUtils.isEmpty(keywordFields)) {
- BooleanQuery booleanQuery2 = new BooleanQuery();
- for (String keywordField : keywordFields) {
- // 是否分词
- if (tokenized == null || !tokenized.booleanValue()) {
- booleanQuery2.add(new TermQuery(new Term(keywordField, keyword.toLowerCase())), BooleanClause.Occur.SHOULD);
- } else {
- booleanQuery2.add(SearchUtils.getBooleanQuery(keywordField, keyword), BooleanClause.Occur.SHOULD);
- }
- }
- booleanQuery.add(booleanQuery2, BooleanClause.Occur.MUST);
- }
- }
- return booleanQuery;
- }
- /**
- * 同时搜索器件、类目、品牌等,并设置boost
- */
- private Query setGoodsBoost(String keyword) {
- BooleanQuery booleanQuery = new BooleanQuery();
- // 前缀搜索(字段并未分词,进行分词搜索时,会有边界问题,如搜索 'BC807-40,215')
- booleanQuery.add(new PrefixQuery(new Term(SearchConstants.GOODS_CMP_CODE_FIELD, keyword.toLowerCase())), BooleanClause.Occur.SHOULD);
- booleanQuery.add(new PrefixQuery(new Term(GOODS_PR_PCMPCODE_FIELD, keyword.toLowerCase())), BooleanClause.Occur.SHOULD);
- // 原厂型号
- booleanQuery.add(createQuery(SearchConstants.GOODS_CMP_CODE_FIELD, keyword, 100), BooleanClause.Occur.SHOULD);
- // 非标
- booleanQuery.add(createQuery(GOODS_PR_PCMPCODE_FIELD, keyword, 100), Occur.SHOULD);
- // 品牌
- booleanQuery.add(createQuery(GOODS_BR_NAME_CN_FIELD, keyword, 10), BooleanClause.Occur.SHOULD);
- booleanQuery.add(createQuery(GOODS_BR_NAME_EN_FIELD, keyword, 10), BooleanClause.Occur.SHOULD);
- // 类目
- booleanQuery.add(createQuery(GOODS_KI_NAME_CN_FIELD, keyword, 1), BooleanClause.Occur.SHOULD);
- // 属性值
- booleanQuery.add(createQuery(SearchConstants.GOODS_CMP_DESCRIPTION_FIELD, keyword, 1), BooleanClause.Occur.SHOULD);
- return booleanQuery;
- }
- @Override
- public List<Map<String, Object>> collectBySearchPCBGoods(String keyword, CollectField collectedField,
- Map<FilterField, Object> filters) throws IOException {
- keyword = recursivelyGetPCBGoodsIds(keyword);
- if (collectedField == null) {
- throw new IllegalArgumentException("参数为空:collectedField");
- }
- IndexSearcher indexSearcher = SearchUtils.getIndexSearcher(SearchConstants.PCB_GOODS_TABLE_NAME);
- List<Map<String, Object>> result = new ArrayList<>();
- try {
- BooleanQuery booleanQuery = queryPCBGoods(keyword);
- setPCBGoodsFilter(filters, booleanQuery);
- logger.info(booleanQuery.toString());
- // 统计
- String uniqueField;
- Set<String> fieldsToLoad = new HashSet<>();
- switch (collectedField) {
- case GOODS_KIND:
- uniqueField = SearchConstants.PCB_GOODS_KI_ID_FIELD;
- fieldsToLoad.add(SearchConstants.PCB_GOODS_KI_ID_FIELD);
- fieldsToLoad.add(SearchConstants.PCB_GOODS_KI_NAME_CN_FIELD);
- break;
- case GOODS_BRAND:
- uniqueField = SearchConstants.PCB_GOODS_BR_ID_FIELD;
- fieldsToLoad.add(SearchConstants.PCB_GOODS_BR_ID_FIELD);
- fieldsToLoad.add(SearchConstants.PCB_GOODS_BR_UUID_FIELD);
- fieldsToLoad.add(SearchConstants.PCB_GOODS_BR_NAME_CN_FIELD);
- fieldsToLoad.add(SearchConstants.PCB_GOODS_BR_NAME_EN_FIELD);
- break;
- case GOODS_CRNAME:
- uniqueField = SearchConstants.PCB_GOODS_CRNAME_FIELD;
- fieldsToLoad.add(SearchConstants.PCB_GOODS_CRNAME_FIELD);
- break;
- default:
- throw new IllegalArgumentException("不支持该统计字段:" + collectedField);
- }
- GoodsGroupCollector collector = new GoodsGroupCollector(uniqueField, fieldsToLoad);
- indexSearcher.search(booleanQuery, collector);
- result = collector.getValues();
- } catch (IOException e) {
- logger.error("", e);
- } finally {
- releaseIndexSearcher(indexSearcher);
- }
- return result;
- }
- /**
- * 获取查询 PCB 批次的query
- *
- * @param keyword
- * @return
- */
- private BooleanQuery queryPCBGoods(String keyword) {
- BooleanQuery booleanQuery = new BooleanQuery();
- if (!SearchUtils.isKeywordInvalid(keyword)) {
- booleanQuery.add(setPCBGoodsBoost(keyword), BooleanClause.Occur.MUST);
- }
- return booleanQuery;
- }
- /**
- * 搜索 PCB,设置boost
- */
- private BooleanQuery setPCBGoodsBoost(String keyword) {
- BooleanQuery booleanQuery = new BooleanQuery();
- // 前缀搜索(字段并未分词,进行分词搜索时,会有边界问题,如搜索 'BC807-40,215')
- booleanQuery.add(new PrefixQuery(new Term(SearchConstants.PCB_GOODS_PR_PCMPCODE_FIELD, keyword.toLowerCase())), BooleanClause.Occur.SHOULD);
- // PCB
- booleanQuery.add(createQuery(SearchConstants.PCB_GOODS_PR_PCMPCODE_FIELD, keyword, 100), Occur.SHOULD);
- // 品牌
- booleanQuery.add(createQuery(SearchConstants.PCB_GOODS_BR_NAME_CN_FIELD, keyword, 10), BooleanClause.Occur.SHOULD);
- booleanQuery.add(createQuery(SearchConstants.PCB_GOODS_BR_NAME_EN_FIELD, keyword, 10), BooleanClause.Occur.SHOULD);
- // 类目
- booleanQuery.add(createQuery(SearchConstants.PCB_GOODS_KI_NAME_CN_FIELD, keyword, 1), BooleanClause.Occur.SHOULD);
- return booleanQuery;
- }
- private BooleanQuery createQuery(String field, String keyword, float boost){
- return createQuery(field, keyword, false, boost);
- }
- private BooleanQuery createQuery(String field, String keyword, boolean useRegexpQuery, float boost){
- BooleanQuery booleanQuery = new BooleanQuery();
- if (StringUtils.isEmpty(field) || StringUtils.isEmpty(keyword)) {
- return booleanQuery;
- }
- // 根据空格分隔关键词,分隔的词取或的关系
- String[] array = keyword.split(" ");
- for(String str : array){
- if(!StringUtils.isEmpty(str)){
- booleanQuery.add(SearchUtils.getBooleanQuery(field, str, useRegexpQuery), Occur.SHOULD);
- }
- }
- booleanQuery.setBoost(boost);
- return booleanQuery;
- }
- /**
- * 过滤
- *
- * @param list
- * 过滤值列表
- * @param field
- * 过滤的字段
- * @param booleanQuery
- * 查询条件
- */
- @SuppressWarnings("unchecked")
- private void filter(Object list, String field, BooleanQuery booleanQuery) {
- List<Object> values;
- if (list instanceof List) {
- values = (List<Object>) list;
- }else{
- values = new ArrayList<>();
- values.add(list);
- }
- BooleanQuery booleanQuery2 = new BooleanQuery();
- for (Object value : values) {
- TermQuery query = new TermQuery(new Term(field, value.toString().toLowerCase()));
- booleanQuery2.add(query, BooleanClause.Occur.SHOULD);
- }
- booleanQuery.add(booleanQuery2, BooleanClause.Occur.FILTER);
- }
- @Override
- public V_Products getProduct(Long id) throws IOException {
- return DocumentToObjectUtils.toProduct(
- SearchUtils.getDocumentById(SearchConstants.PRODUCTS_PRIVATE_TABLE_NAME, SearchConstants.PRODUCT_PRIVATE_ID_FIELD, id));
- }
- /**
- * 获取标准型号联想词
- *
- * @param keyword 关键词
- * @param size 尺寸
- * @return
- */
- @Override
- public List<Map<String, Object>> getSimilarPCmpCodes(String keyword, Integer size) {
- size = size == null || size < 1 ? SIMILAR_NUM_EIGHT : size;
- if (SearchUtils.isKeywordInvalid(keyword)) {
- throw new IllegalArgumentException("输入无效:" + keyword);
- }
- IndexSearcher indexSearcher = SearchUtils.getIndexSearcher(SearchConstants.PRODUCTS_PRIVATE_TABLE_NAME);
- List<Map<String, Object>> products = new ArrayList<>();
- try {
- PrefixQuery prefixQuery = new PrefixQuery(
- new Term(SearchConstants.PRODUCT_PRIVATE_PCMPCODE_FIELD, keyword.toLowerCase()));
- logger.info(prefixQuery.toString());
- Sort sort = new Sort(new SortField(SearchConstants.PRODUCT_PRIVATE_PCMPCODE_FIELD, new StringFieldComparatorSource(keyword)));
- TopDocs hits = indexSearcher.search(prefixQuery, size, sort);
- ScoreDoc[] scoreDocs = hits.scoreDocs;
- for (ScoreDoc scoreDoc : scoreDocs) {
- Set<String> fieldsToLoad = new HashSet<>();
- fieldsToLoad.add(SearchConstants.PRODUCT_PRIVATE_PCMPCODE_FIELD);
- Document document = indexSearcher.doc(scoreDoc.doc, fieldsToLoad);
- Map<String, Object> map = new HashMap<>();
- map.put("pCmpCode", document.get(SearchConstants.PRODUCT_PRIVATE_PCMPCODE_FIELD));
- products.add(map);
- }
- } catch (IOException e) {
- logger.error("", e);
- } finally {
- releaseIndexSearcher(indexSearcher);
- }
- return products;
- }
- /**
- * 获取类目联想词
- *
- * @param keyword 关键词
- * @param size 尺寸
- * @return
- */
- @Override
- public List<Map<String, Object>> getSimilarKind(String keyword, Integer size) {
- size = size == null || size < 1 ? SIMILAR_NUM_EIGHT : size;
- if (SearchUtils.isKeywordInvalid(keyword)) {
- throw new IllegalArgumentException("输入无效:" + keyword);
- }
- IndexSearcher indexSearcher = SearchUtils.getIndexSearcher(SearchConstants.PRODUCTS_PRIVATE_TABLE_NAME);
- List<Map<String, Object>> products = new ArrayList<>();
- try {
- PrefixQuery prefixQuery = new PrefixQuery(
- new Term(SearchConstants.PRODUCT_PRIVATE_KIND_FIELD, keyword.toLowerCase()));
- logger.info(prefixQuery.toString());
- Sort sort = new Sort(new SortField(SearchConstants.PRODUCT_PRIVATE_KIND_FIELD, new StringFieldComparatorSource(keyword)));
- TopDocs hits = indexSearcher.search(prefixQuery, size, sort);
- ScoreDoc[] scoreDocs = hits.scoreDocs;
- for (ScoreDoc scoreDoc : scoreDocs) {
- Set<String> fieldsToLoad = new HashSet<>();
- fieldsToLoad.add(SearchConstants.PRODUCT_PRIVATE_KIND_FIELD);
- Document document = indexSearcher.doc(scoreDoc.doc, fieldsToLoad);
- Map<String, Object> map = new HashMap<>();
- map.put("kind", document.get(SearchConstants.PRODUCT_PRIVATE_KIND_FIELD));
- products.add(map);
- }
- } catch (IOException e) {
- logger.error("", e);
- } finally {
- releaseIndexSearcher(indexSearcher);
- }
- return products;
- }
- @Override
- public Kind getKind(Long id) throws IOException {
- return DocumentToObjectUtils.toKind(
- SearchUtils.getDocumentById(SearchConstants.KIND_TABLE_NAME, SearchConstants.KIND_ID_FIELD, id));
- }
- @Override
- public Brand getBrand(Long id) throws IOException {
- return DocumentToObjectUtils.toBrand(
- SearchUtils.getDocumentById(SearchConstants.BRAND_TABLE_NAME, SearchConstants.BRAND_ID_FIELD, id));
- }
- @Override
- public Component getComponent(Long id) throws IOException {
- return DocumentToObjectUtils.toComponent(SearchUtils.getDocumentById(SearchConstants.COMPONENT_TABLE_NAME,
- SearchConstants.COMPONENT_ID_FIELD, id));
- }
- @Override
- public Goods getGoods(String id) throws IOException {
- return DocumentToObjectUtils.toGoods(
- SearchUtils.getDocumentById(SearchConstants.GOODS_TABLE_NAME, SearchConstants.GOODS_GO_ID_FIELD, id));
- }
- @Override
- public PCBGoods getPCBGoods(String id) throws IOException {
- return DocumentToObjectUtils.toPCBGoods(
- SearchUtils.getDocumentById(SearchConstants.PCB_GOODS_TABLE_NAME, SearchConstants.PCB_GOODS_GO_ID_FIELD, id));
- }
- @Override
- public SPage<Object> getObjects(String tableName, String keyword, String field, Boolean tokenized, @NotEmpty("page") Integer page, @NotEmpty("size") Integer size) throws IOException {
- if (keyword == null) {
- keyword = "";
- }
- if (field == null) {
- field = SearchUtils.getIdField(tableName);
- }
- if (tokenized == null) {
- tokenized = false;
- }
- IndexSearcher indexSearcher = SearchUtils.getIndexSearcher(tableName);
- SPage<Object> sPage = new SPage<>();
- try {
- Query query;
- if (tokenized) {
- query = SearchUtils.getBooleanQuery(field, keyword);
- } else {
- query = new TermQuery(new Term(field, keyword));
- }
- // 分页信息
- if (page > 0) {
- sPage.setPage(page);
- } else {
- sPage.setPage(1);
- sPage.setFirst(true);
- }
- if (size > 0) {
- sPage.setSize(size);
- } else {
- sPage.setSize(20);
- }
- TopDocs topDocs;
- // 如果页码不为1
- if (sPage.getPage() > 1) {
- TopDocs previousTopDocs = indexSearcher.search(query, (sPage.getPage() - 1) * sPage.getSize());
- int totalHits = previousTopDocs.totalHits;
- ScoreDoc[] previousScoreDocs = previousTopDocs.scoreDocs;
- if ((sPage.getPage() - 1) * sPage.getSize() >= totalHits) {
- throw new IllegalArgumentException("页码过大:元素总数量为" + totalHits);
- }
- topDocs = indexSearcher.searchAfter(previousScoreDocs[previousScoreDocs.length - 1], query,
- sPage.getSize());
- } else {
- sPage.setFirst(true);
- topDocs = indexSearcher.search(query, sPage.getSize());
- }
- int totalHits = topDocs.totalHits;
- // 设置总元素个数、页数等信息
- sPage.setTotalElement(totalHits);
- int totalPage = (int) Math.ceil(totalHits / (1.0 * sPage.getSize()));
- sPage.setTotalPage(totalPage);
- if (totalPage == sPage.getPage()) {
- sPage.setLast(true);
- }
- List<Object> content = new ArrayList<>();
- for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
- Document document = indexSearcher.doc(scoreDoc.doc);
- content.add(DocumentToObjectUtils.toObject(document, tableName));
- }
- sPage.setContent(content);
- } finally {
- releaseIndexSearcher(indexSearcher);
- }
- return sPage;
- }
- }
|