全文索引 超长中文截断问题

v2.0.1
全文索引

内容包含比较长的句子,因为全文索引限制256个字节,导致存在中文字符被截断的风险。
截断后在es那边无法识别为utf8【Invalid UTF-8 middle byte 0x22\n at [Source: org.elasticsearch.common.bytes.BytesReference$MarkSupportingStreamInputWrapper@357e8a0】,导致创建索引失败。
然后会导致【A fatal error . Full-text engine is not working.】之类的错误。
之后会死循环创建索引环节。
看代码确实是直接截断的。

好问题,
UTF8下普通的中文字符占3个字节, 256/3 还多着一个字符,导致一个无效的字符(一个中文字符的一个字节)。

后面nebula字符集功能会统一处理的。

嗯嗯 我这边快要上线了,看了一下【MAX_INDEX_TYPE_LENGTH】相关的好像就是storage里面用到了,我尝试着自己编译一个不受限制的版本试试看,本身内容也不会特别长,但有一些内容肯定超过了256字节。

不知道nebula这边会在哪一版修复这个问题?

字符集是一个比较大的功能。我们先需求评审吧。

好的,谢谢回复!


# 拉取nebula开发环境
git clone https://github.com/vesoft-inc/nebula-dev-docker.git

# 拉取nebula开发环境docker
sudo docker pull vesoft/nebula-dev:centos7

# 启动docker进入docker环境
sudo ./run.sh

# 新建目录
mkdir -p /data/code/
cd /data/code/

# 拉取storage代码
git clone -b v2.0.1 https://github.com/vesoft-inc/nebula-storage.git

# 创建构建目录
cd nebula-storage
mkdir build

# 下载common源码
cmake -DENABLE_BUILD_STORAGE=on -DENABLE_TESTING=OFF -DCMAKE_BUILD_TYPE=Release -DNEBULA_COMMON_REPO_TAG=v2.0.1 ..


# 修改索引限制和docID 长度限制
vim ../modules/common/src/common/plugin/fulltext/FTUtils.h

# 清空build目录重新生成cmake文件
rm -rf *
cmake -DENABLE_BUILD_STORAGE=on -DENABLE_TESTING=OFF -DCMAKE_BUILD_TYPE=Release -DNEBULA_COMMON_REPO_TAG=v2.0.1 ..

# 编译
nohup make &

# 将镜像中二进制文件拷贝出来
sudo docker cp containerid:/data/nebula-storage/build/bin/nebula-storaged /data/nebula/code/nebula-dev-docker/nebula/

目前我的解决方案就是简单定义一下自己的值。当然大家可以根据业务来,或者这里的256字节动态计算,只要不对多字节字符进行截断就无大碍。
修改文件:/data/nebula-storage/modules/common/src/common/plugin/fulltext/FTUtils.h

// 自定义了两个长度
// 放开256限制
#define MAX_VALUE_LEN 2147483647
// es文档ID长度是512字节,所以这里还是流出256个字节吧
#define MAX_ID_LEN 256
...

    static std::string val(const std::string &v) {
        return ((v.size() > MAX_VALUE_LEN) ? v.substr(0, MAX_VALUE_LEN) : v);
    }
    static std::string docId(const DocItem& item) {
        // partId_schemaId_column_value,
        // The value length limit is 255 bytes
        // docId structure : partId(10bytes) + schemaId(10Bytes) +
        //                   columnName(32bytes) + encoded_val(max 344bytes)
        // the max length of docId is 512 bytes, still have about 100 bytes reserved
        // 这里替换一下MAX_VALUE_LEN即可。
        auto encoded = encryption::Base64::encode((item.val.size() > MAX_ID_LEN)
                                                   ? item.val.substr(0, MAX_ID_LEN)
                                                   : item.val);
        std::replace(encoded.begin(), encoded.end(), '/', '_');
        std::stringstream ss;
        ss << id(item.part) << id(item.schema) << column(item.column) << encoded;
        return ss.str();
    }

此话题已在最后回复的 7 天后被自动关闭。不再允许新回复。