这几天在工作中遇到一个关于docValue的小问题,特此记录一下。
问题是这样的,同事在用solr对一个字段进行facet操作的时候,报出了一个错误
you are intending to use sorting,facet,group or other statistic feature, please set field:[ex_payModeDetailName] docValue property 'true'
错误提示也很明显,就是在做facet时要把这个字段的docValue打开,所以就照着做了
<dynamicField name="ex_*" type="string" stored="true" indexed="true" multiValued="false" docValues="true"/>
重新做了一遍全量,发现还是报同样的错误,感觉非常奇怪,按理说这个错误也算很常见了,也很具体,别的字段这个错误这种方式就能解决,怎么这个不行呢,难道跟这个自定义字段有关系?
查看了一下这个自定义字段,就是从一个json的字段中,解析出各个key,重新组装成动态字段。所以去看了一下这个自定义字段的代码,发现了问题所在,核心代码如下
for (String key : json.keySet()) {
field = new SchemaField(propPrefix + key, sf.getType(),
OMIT_NORMS | OMIT_TF_POSITIONS | STORED | INDEXED, "");
fieldValue = String.valueOf(json.get(key));
if ("null".equalsIgnoreCase(fieldValue)
|| (filterKeys != null && !this.filterKeys.contains(key))) {
continue;
}
result.add(docVal);
}
result.add(this.createField(field, fieldValue, 1.0f));
}
即在字段定义的时候,就定义了字段的类型为OMIT_NORMS | OMIT_TF_POSITIONS | STORED | INDEXED,并没有docValue,所以在schema.xml中定义并不能真正意义上的打开dcoValue的开关,好吧,找到了问题所在进行修改,对需要打开的json的key的field如下操作
field = new SchemaField(propPrefix + key, sf.getType(),
OMIT_NORMS | OMIT_TF_POSITIONS | STORED | INDEXED | DOC_VALUES, "");
ok,又做了一次全量发布,让同事进行测试一下,很可惜,反馈依旧是这个错误,难以理解。
最后无奈咨询了一下百岁,他看了一下指出了问题所在。
在上面的代码中,我们定义了一个打开docValue的Field,然后调用了基类也就是FieldType的createField方法,深入到这个方法中
public IndexableField createField(SchemaField field, Object value, float boost) {
if (!field.indexed() && !field.stored()) {
if (log.isTraceEnabled())
log.trace("Ignoring unindexed/unstored field: " + field);
return null;
}
String val;
try {
val = toInternal(value.toString());
} catch (RuntimeException e) {
throw new SolrException( SolrException.ErrorCode.SERVER_ERROR, "Error while creating field '" + field + "' from value '" + value + "'", e);
}
if (val==null) return null;
org.apache.lucene.document.FieldType newType = new org.apache.lucene.document.FieldType();
newType.setTokenized(field.isTokenized());
newType.setStored(field.stored());
newType.setOmitNorms(field.omitNorms());
newType.setIndexOptions(field.indexed() ? getIndexOptions(field, val) : IndexOptions.NONE);
newType.setStoreTermVectors(field.storeTermVector());
newType.setStoreTermVectorOffsets(field.storeTermOffsets());
newType.setStoreTermVectorPositions(field.storeTermPositions());
newType.setStoreTermVectorPayloads(field.storeTermPayloads());
return createField(field.getName(), val, newType, boost);
}
方法中并没有对我们设定的docValue值进行什么操作,所以证明我们的这种方式并没有真正的打开docValue,那该如何正确的打开docValue呢?参考一下StrField中的方式。
@Override
public List<IndexableField> createFields(SchemaField field, Object value, float boost) {
IndexableField fval = createField(field, value, boost);
if (field.hasDocValues()) {
IndexableField docval;
final BytesRef bytes = new BytesRef(value.toString());
if (field.multiValued()) {
docval = new SortedSetDocValuesField(field.getName(), bytes);
} else {
docval = new SortedDocValuesField(field.getName(), bytes);
}
// Only create a list of we have 2 values...
if (fval != null) {
List<IndexableField> fields = new ArrayList<>(2);
fields.add(fval);
fields.add(docval);
return fields;
}
fval = docval;
}
return Collections.singletonList(fval);
}
即要自定义一个类似SortedSetDocValuesField的field,参考这个思路,修改了代码
for (String key : json.keySet()) {
field = new SchemaField(propPrefix + key, sf.getType(),
OMIT_NORMS | OMIT_TF_POSITIONS | STORED | INDEXED | DOC_VALUES, "");
fieldValue = String.valueOf(json.get(key));
if ("null".equalsIgnoreCase(fieldValue)
|| (filterKeys != null && !this.filterKeys.contains(key))) {
continue;
}
if(this.docValueKeys != null && this.docValueKeys.contains(key)){
BytesRef bytes = new BytesRef(fieldValue);
IndexableField docVal = new SortedDocValuesField(propPrefix + key,bytes);
result.add(docVal);
}
result.add(this.createField(field, fieldValue, 1.0f));
}
再进行一次全量写入,解决了问题。
PROBLEM SOLVED!
分享到:
相关推荐
这通常涉及到修改`schema.xml`或`managed-schema`文件,定义新的查询字段类型和查询解析器。例如,可以创建一个新的查询解析器,专门为自定义打分设计。 此外,Solr还支持插件开发,可以编写自定义的`Similarity`类...
为了在Solr中使用自定义评分组件,你需要在Solr配置文件(如`solrconfig.xml`)中注册这个组件,并在schema配置中指定字段使用该组件。此外,可能还需要配置Solr服务器以加载自定义的JAR文件,这可以通过`lib`标签来...
自定义的Solr 分词器,可以通过竖线"|"来分词,可以在博客http://blog.csdn.net/jiangchao858/article/details/68954044看到生成过程与使用步骤。
转换为DOC格式的Apache Solr Ref Guide 7.5适用于那些希望对文档进行个性化修改,如添加笔记、高亮或自定义排版的用户。 Solr 7.5的核心特性包括: 1. **全文索引**:Solr能够对大量文本数据进行高效的全文搜索,...
solr7.5官方文档是pdf格式,经本人转换成doc,可供阅读参考
Solr学习笔记.doc
最后,"文档、字段和模式设计" 部分则深入探讨了如何优化索引结构以满足复杂的搜索需求,包括模式 API 的使用和自定义字段类型的定义等。 通过阅读官方文档,用户不仅能够掌握 Solr 的安装、配置、索引和搜索等基础...
solr functionquery函数查询功能强大,但字符串函数比较缺乏,该示例是contain示例,表示值中包含传入的字符串即返回1 否则返回0,可用于solr查询中如果某个字段包含动态传入的值在排名优先。有其他查询排序需求...
3. **配置Schema.xml**:在 Solr 的 schema.xml 文件中,我们需要定义字段类型(FieldType)并指定使用 ikanalyzer。例如,可以创建一个名为 `text_ik` 的字段类型,并设置其`analyzer_class`属性为 `org.apache....
5. **字段类型与分析器**:Solr允许自定义字段类型和分析器,以适应不同数据格式和语言的处理,如英文分词、中文分词等。 6. ** faceted search(面导航)**:提供丰富的分类和过滤选项,帮助用户更方便地浏览和...
5. **字段类型和分析器**:Solr允许用户自定义字段类型,如文本、日期、数字等,并配置相应的分析器,用于处理数据的预处理,如分词、去除停用词等,从而提高搜索质量。 6. ** faceting(分面导航)和高亮显示**:...
1. **修改 schema.xml 文件**:打开 `D:\solr\home` 目录下的 schema.xml 文件,增加或修改以下字段类型定义: ```xml <fieldType name="textComplex" class="solr.TextField" positionIncrementGap="100"> ...
`schema.xml`(在较新版本中为managed schema)用于定义字段类型和字段,以及文档结构。 5. **请求处理器**:Solr提供多种请求处理器,如标准请求处理器(StandardRequestHandler)用于处理默认的搜索请求,更新...
Solr的灵活性和可扩展性得益于其插件系统,使得用户可以根据需求自定义功能。下面我们将深入探讨Solr的各种插件及其在实际应用中的作用。 1. **查询解析器插件**: 查询解析器是Solr处理用户输入查询的关键组件。...
3. **配置与部署**:Solr的配置文件位于`conf`目录下,包括schema.xml(定义字段和字段类型)、solrconfig.xml(配置索引和查询参数)等。用户可以根据需求自定义这些配置。部署Solr通常涉及解压下载的`solr-4.10.3....
Schema是Solr的核心配置之一,用于定义索引字段、数据类型、分析器等,它允许用户自定义字段的属性,以满足不同数据的处理需求。 1.2.3 查询 Solr提供丰富的查询语法,包括布尔运算、短语匹配、范围查询等,还支持...