OpenSearch 简单学习

本文介绍如何利用阿里云OpenSearch实现高效搜索功能。从搭建环境、数据上传到编写搜索代码,详细展示了OpenSearch的使用流程及注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

项目中用到了阿里云的开放搜索,进行一下总结。
OpenSearch基于阿里巴巴自主研发的大规模分布式搜索引擎平台,该平台承载了阿里巴巴全部主要搜索业务,包括淘宝、天猫、一淘、1688、ICBU、神马搜索等业务。OpenSearch以平台服务化的形式,将专业搜索技术简单化、低门槛化和低成本化,让搜索引擎技术不再成为客户的业务瓶颈,以低成本实现产品搜索功能并快速迭代。
注册阿里云
注册
在服务中找到开放搜索,添加到自己的产品和服务里面。
这里写图片描述
进入以后提示错误
这里写图片描述

这个时候就需呀设置
这里写图片描述
我选择继续使用accesskey
这里写图片描述
那就创建一个key
这里写图片描述
这次就可以进入开放搜索了
这里写图片描述
内部就是这个样子
这里写图片描述
创建
这里写图片描述
注意这里,我为了理解方便选择了手动创建。
这里写图片描述

literal 类型我觉的可以理解为文本,主键我没有选择这个。而是用的int类型
可以看不是主键的就可以有多种数据类型可供选择,

这里写图片描述
注意里面的索引,现在index 里包含了两个字段,也就是说会从这两个字段里面找到匹配的内容。
分词方式选择了默认的中文基础分词。
这里写图片描述
创建完成
这里写图片描述
之后激活就可以了,我选择的是最低配置,这个配置现在是处于免费里面的。
接下来就是要上传数据了
这里我选择通过文件上传,当然这只是测试的时候比较实用,正常大量数据的话需要SDK上传。
这是我的测试数据,json格式传送。

 [
  {
    "fields": {
      "test_id": 1,
      "test_name": "香蕉 ",
      "test_content": " 很好吃,深受女性喜爱的功效。"
    },
    "cmd": "ADD"
  },
  {
    "fields": {
      "test_id": 2,
      "test_name": "苹果",
      "test_content": " 可以减肥,适合需要减轻体重的人"
    },
    "cmd": "ADD"
  },
  {
    "fields": {
      "test_id": 3,
      "test_name": "葡萄",
      "test_content": "被称为黑珍珠,自古昏君最喜欢吃"
    },
    "cmd": "ADD"
  },
  {
    "fields": {
      "test_id": 4,
      "test_name": "梨 ",
      "test_content": "适合糖尿病人的水果"
    },
    "cmd": "ADD"
  },
  {
    "fields": {
      "test_id": 5,
      "test_name": "西瓜",
      "test_content": "夏天解暑神器"
    },
    "cmd": "ADD"
  }
]

在配置好,搜索结果以后我们可以看到在搜索结构中查看。

现在这些都是都是通过界面调用的,下面需要写代码正常应用中调用。
需要引入的包

import com.alibaba.fastjson.JSON;
import com.aliyun.opensearch.CloudsearchClient;
import com.aliyun.opensearch.CloudsearchSearch;
import com.aliyun.opensearch.object.KeyTypeEnum;
CloudsearchClient client;//客户

public SearchResultJson search(String json) {
        logger.info("--------------------openSearch搜索商品开始----------------------------");
        SearchResultJson searchResultJson = new SearchResultJson();
        int total = 0;
        //创建客户端
        try {
            this.client = new CloudsearchClient(accesskey, secret , host, opts, KeyTypeEnum.ALIYUN);
        } catch (UnknownHostException e1) {
            e1.printStackTrace();
        }
        Map<String, Object> data = new HashMap<String, Object>();
        data = JSON.parseObject(json, Map.class);
        CloudsearchSearch search = new CloudsearchSearch(client);
        // 添加指定搜索的应用:
        search.addIndex(appName);
        // 指定搜索返回的格式。
        search.setFormat("json");

        if(data != null){
            if(data.get("priceSort") != null && data.get("priceSort").equals("1")){//价格升序
                // 设定排序方式 + 表示正序 - 表示降序
                search.addSort("price", "+");
            }else if(data.get("priceSort") != null && data.get("priceSort").equals("0")){//价格降序
                search.addSort("price", "-");
            }
            if(data.get("saleNum") != null && data.get("saleNum").equals("1")){//销量升序
                search.addSort("soldnum", "+");
            }else if(data.get("saleNum") != null && data.get("saleNum").equals("0")){//销量降序
                search.addSort("soldnum", "-");
            }
            if(data.get("keyword") != null && !"".equals(data.get("keyword").toString().trim())){//关键词
                String keyword = data.get("keyword").toString().trim();
                String tempKeyword = keyword.replaceAll("\\s{1,}", " ");
                String[] keywords = tempKeyword.split(" ");
                List<String> keywordList = new ArrayList<String>();
                for(int i = 0; i < keywords.length; i++){
                    if(keywordList.contains(keywords[i]))
                        continue;
                    else
                        keywordList.add(keywords[i]);
                }
                keywords = keywordList.toArray(new String[keywordList.size()]);
                StringBuilder text = new StringBuilder();
                for(int i = 0; i < keywords.length; i++){
                    text.append("default:").append("'").append(keywords[i]).append("'").append(" AND ");
                }
                if(text.length()>0){
                    search.setQueryString("default:" + text.toString().substring(0, text.toString().lastIndexOf(" AND")));
                }else{
                    search.setQueryString("default:" + text.toString());
                }
                search.setQueryString("default:'" + tempKeyword + "'");
            }
            if(data.get("lowPrice") != null && !"".equals(data.get("lowPrice").toString().trim())){//开始价格
                search.addFilter("price>="+data.get("lowPrice"));
            } 
            if(data.get("propertyStr") != null && !"".equals(data.get("propertyStr").toString().trim())){//开始价格
                String propertyStr = (String) data.get("propertyStr");
                String[] propertyArr = null;
                if(propertyStr.contains(",")){
                    propertyArr = propertyStr.split(",");
                    for(int i = 0; i < propertyArr.length; i++){
                        StringBuilder text = new StringBuilder();
                        text.append('"').append(propertyArr[i]).append('"');
                        search.addFilter("property="+text.toString());
                    }
                }else{
                    StringBuilder text = new StringBuilder();
                    text.append('"').append(data.get("propertyStr")).append('"');
                    search.addFilter("property="+text.toString());
                }
            } 
            if(data.get("hignPrice") != null && !"".equals(data.get("hignPrice").toString().trim())){//结束价格
                search.addFilter("price<="+data.get("hignPrice"));
            } 
            if(data.get("pageIndex") != null && !"".equals(data.get("pageIndex").toString().trim())){//页码
                search.setStartHit(((int)data.get("pageIndex")-1) * 10);
            }
            if(data.get("supplierId") != null && !"".equals(data.get("supplierId").toString().trim())){//页码
                search.addFilter("supplierid="+data.get("supplierId").toString().trim());
            }
            if(data.get("flag") != null && !"".equals(data.get("flag").toString().trim())){//页码
                if(data.get("flag").equals(BY_SUPPLIER)){
                    search.addAggregate("listname2", "count()");
                }else if(data.get("flag").equals(BY_COMMON)){
                    search.addAggregate("property", "count()");
                }
            }
            search.setHits(10);

            try {
                Map<String, Object> tempResult = JSON.parseObject(search.search(),Map.class);
                Map<String, Object> middleTempResult = (Map<String, Object>) tempResult.get("result");
                total = (int) middleTempResult.get("total");//总数

                //-----------------查询商品结果-------------------
                List<Map<String, Object>> result = (List<Map<String, Object>>) middleTempResult.get("items");
                logger.info("\n###搜索商品列表结果:" + result +"\n");
                List<Product> products = new ArrayList<Product>();
                for(Map<String, Object> object : result){
                    Product product = new Product();
                    String prodId = (String)object.get("prodid");
                    if(!StringUtils.isEmpty(prodId)){
                        product.setProdId(Long.parseLong(prodId));
                    }
                    product.setName((String)object.get("name"));
                    product.setCode((String)object.get("code"));
                    String price = (String)object.get("price");
                    if(!StringUtils.isEmpty(price)){
                        product.setPrice(new BigDecimal(price));
                    }
                    product.setDescription((String)object.get("description"));
                    product.setSupplierName((String)object.get("suppliername"));
                    product.setMainProdPicUrl((String)object.get("mainprodpicurl"));
                    String skuCount = (String)object.get("skucount");
                    product.setSkuCount(Integer.parseInt(skuCount));
                    product.setPropertyStr((String)object.get("propertystr"));
                    products.add(product);
                }

                //--------------------查询分类-------------
                List<Map<String, Object>> facet = (List<Map<String, Object>>) middleTempResult.get("facet");//分类结果
                logger.info("\n###搜索商品分类列表:" + facet +"\n");
                List<Property> propertyList= new ArrayList<Property>();
                if(data.get("flag") != null && !"".equals(data.get("flag").toString().trim())){//页码
                    if(data.get("flag").equals(BY_SUPPLIER)){
                        for(Map<String, Object> property : facet){
                            List<Map<String, Object>> properties = (List<Map<String, Object>>) property.get("items");
                            for(Map<String, Object> prop : properties){
                                String facetValue = (String) prop.get("value");
                                Long count = Long.parseLong((String) prop.get("count"));
                                Property propTemp = new Property();
                                propTemp.setName(facetValue);
                                propTemp.setCount(count);
                                propertyList.add(propTemp);
                            }
                        }
                    }else if(data.get("flag").equals(BY_COMMON)){
                        for(Map<String, Object> property : facet){
                            List<Map<String, Object>> properties = (List<Map<String, Object>>) property.get("items");
                            for(Map<String, Object> prop : properties){
                                String facetValue = (String) prop.get("value");
                                Long count = Long.parseLong((String) prop.get("count"));
                                Property propTemp = new Property();
                                propTemp.setName(facetValue.substring(0, facetValue.indexOf(":")));
                                propTemp.setValue(facetValue.substring(facetValue.indexOf(":")+1));
                                propTemp.setCount(count);
                                propertyList.add(propTemp);
                            }
                        }
                    }
                }

                searchResultJson.setProducts(products);
                searchResultJson.setProperties(propertyList);
                searchResultJson.setTotal(total);
            } catch (ClientProtocolException e) {
                logger.error("OpenSearch客户端协议异常!", e);
                throw new PurchaseException(OperCodeDefine.OPEN_SEARCH_CLIENT_PROTOCOL_EXCEPTION, OperCodeDefine.OPEN_SEARCH_CLIENT_PROTOCOL_EXCEPTION_NAME);
            } catch (UnknownHostException e) {
                logger.error("创建OpenSearch客户端时发生异常:未知主机异常!", e);
                throw new PurchaseException(OperCodeDefine.OPEN_SEARCH_UNKNOWN_HOST_EXCEPTION, OperCodeDefine.OPEN_SEARCH_UNKNOWN_HOST_EXCEPTION_NAME);
            } catch (IOException e) {
                logger.error("OpenSearch上传文档IO操作异常!", e);
                throw new PurchaseException(OperCodeDefine.OPEN_SEARCH_IO_ERROR, OperCodeDefine.OPEN_SEARCH_IO_ERROR_NAME);
            }
        }
        return searchResultJson;
    }
### OpenSearch 在 Java 环境中的集成与使用 OpenSearch 是一种开源搜索引擎,旨在提供类似于 Elasticsearch 的功能,同时支持更广泛的社区贡献。在 Java 环境下,开发者可以通过多种方式实现 OpenSearch 的集成和开发。 #### 1. 客户端库的选择 为了简化 OpenSearch 和 Java 应用程序之间的交互,官方提供了专门的客户端库 `opensearch-java`。该库允许开发者通过简单的 API 调用来执行索引操作、查询数据以及管理集群状态[^4]。以下是基本依赖项配置: 对于 Maven 用户: ```xml <dependency> <groupId>org.opensearch.client</groupId> <artifactId>opensearch-rest-high-level-client</artifactId> <version>2.9.0</version> </dependency> ``` Gradle 配置如下: ```gradle implementation 'org.opensearch.client:opensearch-rest-high-level-client:2.9.0' ``` #### 2. 基本连接设置 建立到 OpenSearch 实例的连接通常涉及创建一个 RESTful 客户端实例,并指定目标节点地址。以下是一个典型的初始化代码片段: ```java import org.opensearch.action.index.IndexRequest; import org.opensearch.action.index.IndexResponse; import org.opensearch.client.RestHighLevelClient; import org.apache.http.HttpHost; public class OpenSearchExample { public static void main(String[] args) throws Exception { RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http")) ); IndexRequest request = new IndexRequest("my-index"); String jsonString = "{" + "\"name\":\"John Doe\"," + "\"age\":30," + "\"city\":\"New York\"" + "}"; request.source(jsonString, XContentType.JSON); IndexResponse response = client.index(request, RequestOptions.DEFAULT); System.out.println(response.getId()); client.close(); } } ``` 此示例展示了如何向名为 `my-index` 的索引插入一条记录并打印其唯一 ID[^5]。 #### 3. 查询数据 除了写入外,读取也是常见的需求之一。可以利用 DSL 构建复杂的搜索条件来检索所需的数据集。下面的例子说明了基于关键字匹配获取文档的方法: ```java import org.opensearch.action.search.SearchRequest; import org.opensearch.action.search.SearchResponse; import org.opensearch.index.query.QueryBuilders; import org.opensearch.search.builder.SearchSourceBuilder; // ... SearchRequest searchRequest = new SearchRequest("my-index"); SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); sourceBuilder.query(QueryBuilders.matchQuery("field_name", "search_value")); searchRequest.source(sourceBuilder); SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); System.out.println(searchResponse.getHits().getTotalHits()); ``` 这里我们构建了一个针对特定字段值进行模糊查找的操作流程[^6]。 #### 4. 数据管道与其他工具协作 正如提到过的 Kafka Connect 提供了一种高效的方式处理大规模实时流式传输任务[^3]。如果项目场景涉及到从消息队列中提取结构化日志事件并将它们存储至 OpenSearch,则可考虑采用这种方式完成自动化迁移过程而无需额外编写自定义逻辑脚本文件等等复杂工作量较大的部分。 另外值得注意的是,在某些情况下可能还需要结合其他框架比如 Spring Boot 来进一步增强应用的功能性和易维护程度等方面表现出来的优势特性等问题解决方案探讨等内容未展开讨论但同样重要值得深入研究学习实践探索发现更多可能性拓展视野增长见识积累经验提升技能水平达到更高层次成就非凡事业创造更大价值回报社会贡献力量造福人类共同进步发展繁荣昌盛美好未来! ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值