OpenSearch 讲解

OpenSearch 讲解文章目录什么是 OpenSearchOp 和 ElasticSearc 对比 opensearchEl 对比数据准备 OpenSearch 的创建我们对 OpenSearch 的使用 API 分类搜索方式目前在用的产品遇到的问题什么是 OpenSearch 开放搜索 OpenSearch 是一款结构化数据搜索托管服务 为移动应用开发者和网站站长提供简单 高效 稳定

什么是OpenSearch

开放搜索(OpenSearch)是一款结构化数据搜索托管服务,为移动应用开发者和网站站长提供简单、高效、稳定、低成本和可扩展的搜索解决方案。

  1. 创建搜索应用
  2. 编辑您的应用结构
  3. 上传数据
  4. 从您的网站或应用程序提交搜索请求
    简单、高效、低成本和可扩展。但要是后期用好,还需慢慢调试。

Open Search 和 Elastic Search对比

open search

优点:

  1. 支持用户上传数据或同步云数据,实时性有保障。(可以节省1-2台服务器)
  2. 应用结构、排序相关性自由定制,搜索服务更个性化。可以自定义粗排精排算法,但是LCU 和查询命中的文档、召回的文档、formula的复杂度、查询的复杂度等都有关系。
  3. 基于阿里巴巴在搜索领域的积累,提供查询分析功能,对用户查询词进行纠错、词权重分析、停用词过滤,让搜索服务更智能。可以自定义分词器,下拉提示等。可以很方便的设置召回结果的粗排精排,并且内置了一些对应的函数。
  4. 可视化的界面、丰富的模板,不用精通代码也能快速创建自己的搜索应用。
  5. 一张OpenSearch表可以支持多个rds及TDDL(mysql)来源表(如分库分表的场景),并且还有一些字段处理插件,这个挺适合咱们的博客场景
    在这里插入图片描述

  6. 提供A/Btest功能,方便进行优化(快速迭代算法)
    在这里插入图片描述
    缺点




  7. open search和es的命中文档数差了一个数量级 通用分词 和es中ik_smark对比
  8. 子账号没有权限
  9. 分词不能使用or进行query
  10. 目前主辅表,仅支持 N:1 或 1:1 的关系,不支持 1:N(即多表数据关联关系中,多的一方只能是主表,且主表只能有1个)。可以进行表拆分或者合并进行应对。但是改动可能较大。
  11. 主辅表需通过应用表外键与附表主键进行数据关联,且表外键只能关联辅表主键。
  12. 最多只支持2层关联。

ElasticSearch

对比

OpenSearch 和 es 查询语句限制

  1. open search直接使用默认的粗排精排算法
    在这里插入图片描述

  2. es和open search 都查询title 和body
    LCU 使用情况
    目前ask的数据测试query,并发25左右,单次查询均值在5ms以内,平均值LCU在0.3左右。
    人工评估结果
    es查询评估平均得分3.50,opensearch查询评估平均得分2.76








Open Search 的创建

一共有三种创建方式:

  1. 通过模板创建应用结构
  2. 通过上传文档创建应用结构
  3. 通过数据源创建应用结构
    步骤:
    1).添加表
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    2).手动修改创建的应用结构
    在这里插入图片描述
    3). 定义索引结构
    1⃣️需放到 query子句中的字段,必须创建为索引(浮点型不支持创建为索引),分词方式详情请参见字段和分词类型。
    需放到 filter子句,sort子句,及函数中涉及字段有明确标识,需设置为属性的字段必须创建为属性。
    分词字段类型无法配置为属性,例如 TEXT,SHORT_TEXT等都不支持,只支持数值字段类型及不分词字段类型配置为属性,例如 int,int_array,float,float_array,double,double_array,literal,literal_array 等字段类型。
    在这里插入图片描述
    同步数据源
    在这里插入图片描述






























我们对Open Search的使用

API 分类

在这里插入图片描述

搜索方式

可以通过http(get、post)形式或Java、PHP sdk方式进行搜索与上传。

目前在用的产品

  1. 添加maven
 
   
   
     com.aliyun.opensearch 
    
   
     aliyun-sdk-opensearch 
    
   
     3.2.0 
    
   
  1. 部分代码
private static SearcherClient searcherClient=null; static { //创建并构造OpenSearch对象 OpenSearch openSearch = new OpenSearch(Constants.ACCESSKEY, Constants.SECRET, Constants.HOST); //创建OpenSearchClient对象,并以OpenSearch对象作为构造参数 OpenSearchClient serviceClient = new OpenSearchClient(openSearch); //创建SearcherClient对象,并以OpenSearchClient对象作为构造参数 searcherClient = new SearcherClient(serviceClient); } / * 配置信息 * @return */ public Config getConfig(List 
  
    appNames,int start,int hit,List 
   
     fields){ //定义Config对象,用于设定config子句参数,指定应用名,分页,数据返回格式等等 Config config = new Config(appNames); config.setStart(start); config.setHits(hit); //设置返回格式为fulljson格式 config.setSearchFormat(SearchFormat.JSON); // 设置搜索结果返回应用中哪些字段 config.setFetchFields(fields); return config; } / * 粗排精排 * @return */ public Rank getRank(int size){ if(size>500){ size=500; } // 设置精排文档 Rank rank=new Rank(); rank.setReRankSize(size); return rank; } / * @param jsonParam 传过来的参数 * { * "filter":"username=\"Joanna_or_zhouzhou\"",//按照某个字段过滤 * "reRankSize":"500",//参与精排的条数 * "fetchFields":"id,title,nickname",//获取的域/字段 * "pageSize":"20",//每页多少条 * "index":"nickname",//索引 * "page":"0",//第几页 注:0为第一页 * "sort":"-id", //-按照某个字段降序 + 按照某个字段增序 最好不要使用sort 耗资源 * "queryWord":"巴掌大的脚印" , //搜索词 * "summary":[ * { * "snippet":"1",//片段数量 * "field":"nickname",//指定的生效的字段。此字段必需为可分词的text类型的字段。 * "len":"50",//片段长度 * "ellipsis":"...",//片段链接符 * "element":"em"//飘红标签 * } * ] * } * @return */ public ResultVo dataDispose(com.alibaba.fastjson.JSONObject jsonParam){ ResultVo resultVo=new ResultVo(); com.alibaba.fastjson.JSONArray jsonArray=new com.alibaba.fastjson.JSONArray(); List 
    
      appNames=new ArrayList<>(); String appName=jsonParam.getString("appName"); if(StringUtils.isEmpty(appName)){ resultVo.setCode(Constants.ERRORHTTPCODE+Constants.PRODUCTCODE+Constants.CODE0001); resultVo.setMessage("app应用名为空"); resultVo.setData(jsonArray); return resultVo; }else{ appNames.add(appName); } if(jsonParam==null || jsonParam.size()<=0){ resultVo.setCode(Constants.ERRORHTTPCODE+Constants.PRODUCTCODE+Constants.CODE0002); resultVo.setMessage("app参数为空"); resultVo.setData(jsonArray); return resultVo; } //搜索词 String queryWord=jsonParam.getString("queryWord"); if(queryWord==null || queryWord.isEmpty()){ resultVo.setCode(Constants.ERRORHTTPCODE+Constants.PRODUCTCODE+Constants.CODE0003); resultVo.setMessage("queryWord为必填项不能为空"); resultVo.setData(jsonArray); return resultVo; }else{ queryWord=queryWord.replaceAll("\\\\"," ").replaceAll("\'"," "); } int start=0; int hit=20; //第几页 注:0为第一页 config=start:20, hit:20, format:xml String page=jsonParam.getString("page"); //每页多少条 String pageSize=jsonParam.getString("pageSize"); //opensearch start+hit<=5000,超过5000会直接报错无结果。 if(page!=null && NumberUtils.isDigits(page) && Integer.valueOf(page)>=0){ if(pageSize!=null && NumberUtils.isDigits(pageSize) && Integer.valueOf(pageSize)>0){ hit=Integer.valueOf(pageSize); } start=Integer.valueOf(page)*hit; if(start+hit>Constants.MAXSEARCHRESULT){ resultVo.setCode(Constants.ERRORHTTPCODE+Constants.PRODUCTCODE+Constants.CODE0004); resultVo.setMessage("查询总数不能超过5000"); resultVo.setData(jsonArray); return resultVo; } } List 
     
       fetchFields=new ArrayList<>(); //获取的域/字段 String fetchFieldStr=jsonParam.getString("fetchFields"); if(fetchFieldStr==null){ resultVo.setCode(Constants.ERRORHTTPCODE+Constants.PRODUCTCODE+Constants.CODE0005); resultVo.setMessage("获取结果域为必填项"); resultVo.setData(jsonArray); return resultVo; }else{ fetchFields.addAll(Arrays.asList(fetchFieldStr.split(","))); } Config config = getConfig(appNames,start,hit,fetchFields); SearchParams searchParams = new SearchParams(config); //参与精排的条数 String reRankSize=jsonParam.getString("reRankSize"); if(reRankSize!=null && NumberUtils.isDigits(reRankSize)){ searchParams.setRank(getRank(Integer.valueOf(reRankSize))); }else{ searchParams.setRank(getRank(200)); } //索引 String index=jsonParam.getString("index"); //-按照某个字段降序 + 按照某个字段增序 最好不要使用sort 耗资源 String queryStr=""; if(index==null){ resultVo.setCode(Constants.ERRORHTTPCODE+Constants.PRODUCTCODE+Constants.CODE0007); resultVo.setMessage("索引不能为空"); resultVo.setData(jsonArray); return resultVo; }else{ queryStr=index+":"+"'"+queryWord+"'"; } //按照某个字段过滤 String filter=jsonParam.getString("filter"); if(filter!=null){ if(filter.indexOf("=")>-1){ int eindex = filter.indexOf("="); String pre = filter.substring(0, eindex); String next = filter.substring(eindex + 1); queryStr+=" AND "+pre+":"+next; } // //这里针对CSDN_User 做处理 提高查询效率 // if("CSDN_User".equals(appName)){ // // }else{ // searchParams.setFilter(filter); // } } String sort=jsonParam.getString("sort"); if(sort!=null){ queryStr=queryStr+"&&sort="+sort; } log.info("querystr:"+queryStr); searchParams.setQuery(queryStr); SearchParamsBuilder paramsBuilder = SearchParamsBuilder.create(searchParams); try { JSONArray summary = jsonParam.getJSONArray("summary"); if(summary!=null && summary.size()>0){ for (int i=0;i 
      
        0){ JSONObject jsonObject = compute_cost.getJSONObject(0); Object lcu = jsonObject.get("value"); log.info("查询成功,消耗LCU:"+lcu); } }else{ resultVo.setData(jsonArray); resultVo.setCode(Constants.ERRORHTTPCODE+Constants.PRODUCTCODE+Constants.CODE00010); Object errors = obj.get("errors"); if(errors!=null){ resultVo.setMessage(errors+""); }else{ resultVo.setMessage("查询失败"); } log.error("查询失败:"+errors); return resultVo; } } catch (OpenSearchException e) { resultVo.setCode(Constants.ERRORHTTPCODE+Constants.PRODUCTCODE+Constants.CODE0008); resultVo.setMessage(e.getMessage()); resultVo.setData(jsonArray); log.error(Constants.ERRORHTTPCODE+Constants.PRODUCTCODE+Constants.CODE0008+" : "+e.getMessage()); return resultVo; } catch (OpenSearchClientException e) { resultVo.setCode(Constants.ERRORHTTPCODE+Constants.PRODUCTCODE+Constants.CODE0009); resultVo.setMessage(e.getMessage()); resultVo.setData(jsonArray); log.error(Constants.ERRORHTTPCODE+Constants.PRODUCTCODE+Constants.CODE0009+" : "+e.getMessage()); return resultVo; } return resultVo; } public ResultVo searchData(com.alibaba.fastjson.JSONObject jsonParam) { ResultVo resultVo = dataDispose(jsonParam); return resultVo; } 
       
      
     
    
  

遇到的问题

  1. 表关联问题
  2. 性能问题 (filter 字段建立索引)
  3. 子账号没有权限导入数据
  4. 目前redis中的数据不能进行关联同步
  5. query分词之后只能and进行搜索

引用:官方文档

备注:

  1. LCU是用来衡量搜索应用计算能力的单位,一个LCU代表搜索集群中10millicores的计算能力,计算资源估算方法:LCU个数=QPS*compute_cost,millicores是CPU资源的单位,即一个核的1/1000, compute_cost是单次查询计算消耗的LCU
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/199841.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月20日 下午12:05
下一篇 2026年3月20日 下午12:05


相关推荐

  • CSS改变鼠标样式(图片)

    CSS改变鼠标样式(图片)下面就来介绍下步骤方法:首页把鼠标图标格式转换成.ico格式,大小为32*32转换格式网址为:https://www.easyicon.net/covert/然后在CSS样式中增加代码:*{cursor:url(../images/shubiao.ico),auto;}大功告成啦~~~说明:图片大小最好是32*32的大小Css中的cursor属性不仅仅需…

    2022年5月31日
    37
  • 工作站与主域间的信任关系失败_变色龙工作站无法卸载

    工作站与主域间的信任关系失败_变色龙工作站无法卸载症状:登陆域用户,出现错误“此工作站和主域间的信任关系失败”,并无法登陆解决方案:1、使用本地用户登录,更改当前“域”为“工作组”(如默认的WORKGROUP等),并输入具有域管理权限的用户名、密码,随后此电脑上的“域”将会被删除;2、重启电脑3、重新使用域用户信息登陆域4、重启电脑5、登陆成功 或者使用域管理员身份登陆DC服务器,从域中删除此计算机应该也可以。…

    2022年10月10日
    4
  • mysql explain ref const_MySQL EXPLAIN 详解「建议收藏」

    mysql explain ref const_MySQL EXPLAIN 详解「建议收藏」一.介绍EXPLAIN命令用于SQL语句的查询执行计划。这条命令的输出结果能够让我们了解MySQL优化器是如何执行SQL语句的。这条命令并没有提供任何调整建议,但它能够提供重要的信息帮助你做出调优决策。先解析一条sql语句,你可以看出现什么内容EXPLAINSELECT*FROMperson,deptWHEREperson.dept_id=dept.didandper…

    2022年10月18日
    5
  • 豆包P图怎么去水印?3步速通实操教程

    豆包P图怎么去水印?3步速通实操教程

    2026年3月12日
    5
  • 静态代理和动态代理详解[通俗易懂]

    静态代理和动态代理详解[通俗易懂]1代理生活中的代理:比如我们生活中比较熟悉的代购、中介、商家等都是属于代理2什么是代理模式代理模式是指:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户类和目标对象之间起到中介的作用。换句话说,使用代理对象,是为了在不修改目标对象的基础上,增强主业务逻辑。客户类真正想要访问的对象是目标对象,但客户类真正可以访问的对象是代理对象。客户类对目标对象的访问是通过访问代理对象来实现的。当然,代理类与目标类要实现同一个接.

    2022年10月10日
    4
  • java线程池参数_java线程池参数设置原则,如何设置线程池参数比较合理?[通俗易懂]

    java线程池参数_java线程池参数设置原则,如何设置线程池参数比较合理?[通俗易懂]线程池的参数应该怎样设置呢?相信对于很多的人来说这也是一个比较难的问题,下面就让我们一起来解决一下,究竟应该如何设置线程池的参数才是最合理的吧!首先在设置参数的时候,有以下的几点是我们需要考虑到的!1、下游系统抗并发的能力多线程给下游系统造成的并发等于你设置的线程数例:假如,是多线程访问数据库,那么就得考虑数据库的连接池大小设置,数据库并发太多影响其qps,会将数据库打挂等问题。假如,是访问下游系…

    2022年5月3日
    53

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号