SOLR 8.5中字符串数组转对象数组的文档结构改造问题
Solr 8.5 实现分隔符字符串数组转结构化对象数组解决方案
问题根源分析
你遇到的核心问题是错误使用TextField类型存储结构化对象,导致Solr将嵌套对象序列化为字符串而非保留其结构;同时原始转换器脚本未正确拆分PersonalInfo中的分隔符字符串,直接引用了不存在的字段(如row.get("PersonalName"))。
步骤1:修正数据导入转换器脚本
首先需要正确拆分PersonalInfo中每个带|分隔的字符串,提取字段值后构建结构化对象:
function CombinePersonalInfoFields(row) { var personalInfoList = row.get("PersonalInfo"); var personalFieldsArr = new java.util.ArrayList(); // 遍历每个带分隔符的PersonalInfo字符串 for (var i = 0; i < personalInfoList.size(); i++) { var personalStr = personalInfoList.get(i); // 转义|后拆分字符串(正则中|是特殊字符) var fields = personalStr.split("\\|"); if (fields.length !== 6) continue; // 过滤格式错误的条目 var personalFieldObj = new org.apache.solr.common.util.SimpleOrderedMap(); personalFieldObj.add("PersonalName", fields[0]); personalFieldObj.add("Prop1", fields[1]); personalFieldObj.add("Prop2", fields[2]); personalFieldObj.add("Prop3", fields[3]); personalFieldObj.add("Age", fields[4]); personalFieldObj.add("Weight", fields[5]); personalFieldsArr.add(personalFieldObj); } // 替换原PersonalInfo字段为结构化数组 row.put("PersonalInfo", personalFieldsArr); return row; } function ProcessAllRows(row) { // 保留原有其他逻辑 CombinePersonalInfoFields(row); return row; }
步骤2:修改Schema支持结构化嵌套对象
Solr 8.5支持直接存储object类型的多值字段,或通过动态字段实现结构化存储,二选一即可:
方案A:使用object类型字段(推荐)
在managed-schema.xml中定义字段:
<!-- 定义多值object类型字段,存储结构化对象数组 --> <field name="PersonalInfo" type="object" multiValued="true" indexed="true" stored="true"/> <!-- 为子字段单独定义类型(可选,优化查询性能) --> <field name="PersonalInfo_PersonalName" type="string" indexed="true" stored="true"/> <field name="PersonalInfo_Age" type="int" indexed="true" stored="true"/> <field name="PersonalInfo_Weight" type="float" indexed="true" stored="true"/>
方案B:使用嵌套文档(复杂场景适用)
如果需要父子文档关联查询,可使用Solr嵌套文档功能,修改脚本和Schema:
脚本修改:
function ProcessAllRows(row) { var personalInfoList = row.get("PersonalInfo"); var childDocs = new java.util.ArrayList(); for (var i = 0; i < personalInfoList.size(); i++) { var personalStr = personalInfoList.get(i); var fields = personalStr.split("\\|"); if (fields.length !== 6) continue; var childDoc = new org.apache.solr.common.util.SimpleOrderedMap(); childDoc.add("id", row.get("ID") + "_personal_" + i); // 子文档唯一ID childDoc.add("PersonalName", fields[0]); childDoc.add("Prop1", fields[1]); childDoc.add("Prop2", fields[2]); childDoc.add("Prop3", fields[3]); childDoc.add("Age", parseInt(fields[4])); // 转换为数值类型 childDoc.add("Weight", parseFloat(fields[5])); childDoc.add("_nest_path_", "/PersonalInfo"); // 指定嵌套路径 childDocs.add(childDoc); } row.put("_childDocuments_", childDocs); row.remove("PersonalInfo"); // 移除原字段 return row; }
Schema修改:
<field name="PersonalName" type="string" indexed="true" stored="true"/> <field name="Prop1" type="string" indexed="true" stored="true"/> <field name="Prop2" type="string" indexed="true" stored="true"/> <field name="Prop3" type="string" indexed="true" stored="true"/> <field name="Age" type="int" indexed="true" stored="true"/> <field name="Weight" type="float" indexed="true" stored="true"/> <field name="_nest_path_" type="string" indexed="true" stored="true"/>
步骤3:验证结果
重新运行数据导入后,查询文档将得到预期的结构化对象数组:
{ "ID": "123", "AnotherProperty": "Value", "PersonalInfo": [ { "PersonalName": "xxx", "Prop1": "xxx", "Prop2": "xxx", "Prop3": "xxx", "Age": 25, "Weight": 65.5 }, { "PersonalName": "yyy", "Prop1": "yyy", "Prop2": "yyy", "Prop3": "yyy", "Age": 30, "Weight": 70.0 } ] }
内容的提问来源于stack exchange,提问作者user8024268
相关产品推荐
相关产品推荐

