更新时间:2024-10-21 GMT+08:00
分享

对接CSS实现在应用中调用分布式搜索

云搜索服务(Cloud Search Service,简称CSS),为您提供托管的分布式搜索引擎服务,完全兼容开源Elasticsearch搜索引擎,支持结构化、非结构化文本的多条件检索、统计、报表。在AstroZero中,通过应用与CSS对接,实现云搜索服务功能。

前提条件

参照如下操作,获取CSS提供服务的URL地址。

  1. 登录云搜索服务控制台。
  2. 在左侧导航栏中,选择“集群管理”。
  3. 在集群管理列表中,获取“内网访问地址”的值。

    图1 获取内网访问地址

新建CSS连接器

  1. 参考登录AstroZero新版应用设计器中操作,进入应用设计器。
  2. 在左侧导航栏中,选择“集成”
  3. 单击“连接器”中的“ 连接器实例”,进入连接器实例页面。
  4. 在左侧导航栏中,选择“数据 > 云搜索”。
  5. 在右侧页面单击“+”,设置云搜索对接参数。

    图2 创建云搜索
    表1 创建CSS连接器参数说明

    参数

    说明

    名称

    新建连接器的名称。命名要求如下:

    • 长度不能超过64个字符,包括前缀命名空间的长度。
      说明:

      名称前的内容为命名空间,在AstroZero中为了避免不同租户间数据的重名,租户在首次创建应用时需要先定义一个命名空间。一个租户只能创建一个命名空间,创建后不支持修改。

    • 必须以英文字母开头,只能由英文字母、数字或单下划线组成,且不能以下划线结尾。

    地址

    CSS服务的内网访问地址,配置为前提条件中获取的值。

    版本

    ElasticSearch的版本号,目前支持版本6和7。

    安全模式

    在安全模式访问集群时,将进行通讯加密及安全认证。安全模式下,若地址未指明协议,将默认使用https。

    用户名

    登录CSS的账号名,开启“安全模式”时,才会显示该参数。

    密码

    登录CSS账号对应的密码,开启“安全模式”时,才会显示该参数。

    使用证书

    仅在使用https协议,且无法通过证书校验时,才需要使用自定义的证书。

    证书

    该证书用于构建客户端,以验证服务端的真实性,当前支持x509格式的证书。开启“使用证书”时,才会显示该参数。

    客户端证书

    该证书用于服务端对客户端的校验,当前支持x.509格式的证书。开启“使用证书”时,才会显示该参数。

    客户端私钥

    该密钥用于客户端证书的解密。开启“使用证书”时,才会显示该参数。

    打包当前配置

    选中该选项后,应用打包时会将当前配置的连接器信息一并打出。例如,如果应用包发布到运行环境,当前配置默认会被同步到运行环境中。如果不勾选,则内容不会打包发布到运行环境,此时需要您参考管理应用中的连接器中操作,创建对应的连接器。

    默认为选中,对信息敏感的场景,建议不勾选。

    索引添加租户标识

    开启时,生成索引的名称和别名自动添加租户前缀(例如:租户标识--名称/别名)。

  6. 设置完成后,单击“保存”。

在脚本中调用连接器

在事件中,调用连接器实现与CSS的对接。

  1. 参考创建空白AstroZero脚本中操作,创建一个空白脚本。
  2. 在脚本编辑器中,输入如下代码,调用一个CSS连接器,并实现索引操作。

    //导入该事件所依赖的标准库文件。es是系统预置的标准库。
    import * as es from 'es'
    
    /
       ES模块部分事件接口调用示例
    */
    
    let indexName1 = "indexName1"
    let indexName2 = "indexName2"
    let aliasName = "alias"
    
    let client = es.newClient('CSS1') //创建客户端需要输入连接器实例名称,这里举例为“CSS1”
    
    //1. 准备,如果已经存在索引,先进行删除(删除索引同时会删除索引内文档)
    let exist = client.checkIndexExist(indexName1)
    if (exist) { client.dropIndex(indexName1) }
    exist = client.checkIndexExist(indexName2)
    if (exist) { client.dropIndex(indexName2) }
    client.createIndex(indexName1) //创建一个没有映射的索引(根据插入的文档动态生成映射)
    
    //2. 插入或更新文档,如果已存在同id文档则更新,不存在则插入
    let doc = {
        "_id": "1001",     //自定义的文档ID,若不指定_id,则自动生成唯一随机的文档ID
        "foo": "apple",
        "bar": 30,
    }
    let docID = client.indexDoc(indexName1, doc) //返回index的文档id
    console.log("docID: ", docID) //此处docID为1001
    
    //3. 批量插入或更新文档
    let docs = [    //再定义两个文档
        {
            "_id": "1002",
            "foo": "banana",
            "bar": 40,
        },
        {
            "_id": "1003",
            "foo": "orange",
            "bar": 50,
            "baz": true,
        }
    ]
    client.bulkIndexDocs(indexName1, docs)
    
    //4. 局部更新文档
    client.updateDocByDocID(indexName1, "1001", {
        bar: 35,     //局部更新,只将bar字段改为35
        qux: "none",    //局部添加新字段和值
    })
    
    //5. 增删改之后可以显式调用refresh进行刷新,否则需等待约1秒之后,才可被搜
    client.refresh(indexName1)
    
    //6. 查记录数
    let count = client.countDocs(indexName1)
    console.log("count: ", count) //应打印3
    
    //7. 按条件查
    let condition = { 
        query: {
            range: {
                bar: { gte: 40 }
            }
        }
    }
    let searchRes = client.search(condition, indexName1)  //查询bar字段大于40的文档
    console.log("searchRes: ", searchRes)   //此处会打印出两个匹配的文档
    
    //8. 按条件更新
    let script = 'ctx._source.bar = 70' 
    let query = {
        match: {
            foo: "apple",
        }
    }
    let updatedCount = client.updateByQuery(indexName1, query, script) //批量更新,把foo为apple的文档的bar都变为70
    console.log("updatedCount: ", updatedCount) //打印出改动的文档数量,此处打印1
    client.refresh(indexName1)
    
    //9. 仅查询id列表
    let idList = client.searchIDList(indexName1, {
        query: {
            match_all: {}   //全部查询
        },
        size: 5  //指定最多搜出5个结果
    })
    console.log("idList: ", idList) //会打印 ["1001","1002","1003"]
    
    //10. 轻量查询(相比于search,query不需要写json条件,只需要简单字符串查询即可)
    let queryRes = client.query("foo:apple", false, indexName1) //查询foo字段为apple的文档, 第二个参数false表示只查前十个文档,为true则为全查
    console.log("queryRes1: ", queryRes) //会有1个查询结果
    queryRes = client.query("foo:apple OR banana", false, indexName1) //除了foo字段为apple的文档,再加上全文查询banana的结果
    console.log("queryRes2: ", queryRes) //会有2个查询结果
    
    //11. 创建第二个索引,自定义映射
    let mp = {
        dynamic: "strict",
        properties: {
            name: { type: "text"    },
            age: {  type: "integer" }
        }
    }
    client.createIndexWithMapping(indexName2, mp)
    
    //12. 获得索引的映射
    let mpRes = client.getMapping(indexName2)
    console.log("mapping: ", mpRes)    //打印出映射
    
    //13. 绑定别名
    client.attachAlias(indexName1, aliasName)
    
    //14. 对别名操作和对索引操作一致
    client.deleteDocByDocID(aliasName, "1001")
    client.refresh(aliasName)
    count = client.countDocs(aliasName)
    console.log("countAfterDelete: ", count) //这里会打印2
    
    //15. 得到别名关联的索引
    let attached = client.getAttachedIndexes(aliasName)
    console.log(attached)   //这里会打印出indexName1
    
    //16. 得到索引管理的别名
    let ali = client.getAlias(indexName1)
    console.log(ali)    //打印出alias的名字
    
    //17. 同时绑定新索引,解绑旧索引
    client.attachAndDetachAlias(indexName2, indexName1, aliasName)
    attached = client.getAttachedIndexes(aliasName)
    console.log(attached)   //打印出indexName2
    
    //18. 获取当前所有索引的基本信息(对应的别名、文档数)
    let catRes = client.cat()
    console.log("catRes: ", catRes)

    其中,es.newClient('NS__CSS1')中“NS__CSS1”为连接器的名称。

  3. 单击脚本编辑器页面上方的,保存脚本。
  4. 保存成功后,单击,运行脚本。
  5. 不用设置输入参数,直接单击测试窗口右上角的
  6. 在日志页签,可查看到创建了索引。

    0826 10:20:14.685|debug|vm[86]>>> AstroZero 1.2.8 - Production on 2019-08-23 14:44:06 2ce004a222b087e3ac55c70d4e2482d7338d81aa debug (<unknown>.ts:0)
    0826 10:20:14.685|debug|vm[86]>>> script: Test_CSS1 1.0.1  (<unknown>.ts:0)
    0826 10:20:14.685|debug|vm[86]>>> locale: zh_CN (<unknown>.ts:0)
    0826 10:20:14.685|debug|vm[86]>>> timezone: (GMT+00:00) Greenwich Mean Time (GMT) (<unknown>.ts:0)
    0826 10:20:14.766|debug|vm[86]>>> docID:  1001 (Test_CSS1.ts:28)
    0826 10:20:14.812|debug|vm[86]>>> count:  3 (Test_CSS1.ts:57)
    0826 10:20:14.815|debug|vm[86]>>> searchRes:  {
        "aggregations": {},
        "hits": [
            {
                "_id": "1002",
                "_index": "indexname1",
                "_score": 1,
                "_source": {
                    "bar": 40,
                    "foo": "banana"
                },
                "_type": "_doc"
            },
            {
                "_id": "1003",
                "_index": "indexname1",
                "_score": 1,
                "_source": {
                    "bar": 50,
                    "baz": true,
                    "foo": "orange"
                },
                "_type": "_doc"
            }
        ],
        "max_score": 1,
        "total": {
            "relation": "eq",
            "value": 2
        }
    } (Test_CSS1.ts:68)
    0826 10:20:14.82|debug|vm[86]>>> updatedCount:  1 (Test_CSS1.ts:78)
    0826 10:20:14.831|debug|vm[86]>>> idList:  [
        "1002",
        "1003",
        "1001"
    ] (Test_CSS1.ts:88)
    0826 10:20:14.833|debug|vm[86]>>> queryRes1:  {
        "_id": "1001",
        "_index": "indexname1",
        "bar": 70,
        "foo": "apple",
        "qux": "none"
    } (Test_CSS1.ts:92)
    0826 10:20:14.835|debug|vm[86]>>> queryRes2:  {
        "_id": "1002",
        "_index": "indexname1",
        "bar": 40,
        "foo": "banana"
    },
    {
        "_id": "1001",
        "_index": "indexname1",
        "bar": 70,
        "foo": "apple",
        "qux": "none"
    } (Test_CSS1.ts:94)
    0826 10:20:14.879|debug|vm[86]>>> mapping:  {
        "age": {
            "type": "integer"
        },
        "name": {
            "type": "text"
        }
    } (Test_CSS1.ts:108)
    0826 10:20:14.898|debug|vm[86]>>> countAfterDelete:  2 (Test_CSS1.ts:117)
    0826 10:20:14.899|debug|vm[86]>>> indexname1 (Test_CSS1.ts:121)
    0826 10:20:14.899|debug|vm[86]>>> alias (Test_CSS1.ts:125)
    0826 10:20:14.908|debug|vm[86]>>> indexname2 (Test_CSS1.ts:130)
    0826 10:20:14.912|debug|vm[86]>>> catRes:  [
        {
            "indexName": "indexname1",
            "aliases": null,
            "docCount": 2
        },
        {
            "indexName": "indexname2",
            "aliases": [
                "alias"
            ],
            "docCount": 0
        }
    ] (Test_CSS1.ts:134)

相关文档