从动态字段中存储了多个值的字段,此数据在输入xml文件中以正确的顺序排列,但是当我们进行搜索时,数据的顺序完全不同。有没有办法控制这个订单?
让我来描述一下这个过程
1-输入文件附带动态字段,其格式为*_foo
2- solr将添加此动态字段中的值,并将值复制到allFoos
3-我们搜索多值字段,并分析其内容。
我们发现allFoos
中存储的值会丢失输入文件给出的顺序。
这个虚拟数据提供了一个关于我们如何处理字段和副本的示例。 然后更改的字段和值的名称进行测试,但预计resut将是相同的。
<dynamicField name="`*_foo`" type="string" indexed="false" stored="true"/>
<field name="`allFoos`" type="string" indexed="true" stored="true" required="false" multiValued="true"/>
<copyField source="`*_foo`" dest="`allFoos`"/>
<add>
<doc>
<field name="field_1_foo" update="set">1</field>
<field name="field_2_foo" update="set">2</field>
<field name="field_3_foo" update="set">3</field>
<field name="field_4_foo" update="set">4</field>
<field name="field_5_foo" update="set">5</field>
<field name="field_6_foo" update="set">6</field>
<field name="field_7_foo" update="set">7</field>
<field name="field_8_foo" update="set">8</field>
<field name="field_9_foo" update="set">9</field>
<field name="field_10_foo" update="set">10</field>
<field name="field_11_foo" update="set">11</field>
<field name="field_12_foo" update="set">12</field>
<field name="field_13_foo" update="set">13</field>
<field name="field_14_foo" update="set">17</field>
<field name="field_15_foo" update="set">15</field>
<field name="field_16_foo" update="set">16</field>
<field name="field_17_foo" update="set">17</field>
<field name="field_18_foo" update="set">18</field>
<field name="field_19_foo" update="set">19</field>
<field name="field_20_foo" update="set">20</field>
<field name="field_21_foo" update="set">21</field>
<field name="field_22_foo" update="set">21</field>
<field name="field_23_foo" update="set">21</field>
<field name="field_24_foo" update="set">21</field>
<field name="field_25_foo" update="set">21</field>
</doc>
</add>
"allFoos": [ "3", "16", "25", "20", "19", "7", "21", "6", "13", "8", "5", "18", "24", "17", "23", "15", "4", "10", "12", "11", "2", "14", "22", "9", "1"]
每次搜索结果都是一样的,我已经多次删除并重新插入相同的数据,并且它总是按照相同的顺序。
感谢您的帮助!
答案 0 :(得分:1)
Yonik Seely在this thread结束时很好地总结了它:
保证维持订单 多值字段中的值。不同领域的顺序不是 保持。
因此,由于您要将25个不同的字段复制到allFoos
,因此无法保证。默认情况下,SolrInputDocument
由LinkedHashMap
支持,但也有一个接受任意Map<String,SolrInputField>
的构造函数,这意味着不应依赖文档中字段的排序。
public SolrInputDocument() {
_fields = new LinkedHashMap<>();
}
public SolrInputDocument(Map<String,SolrInputField> fields) {
_fields = fields;
}
作为文档提取过程的一部分,您可以预处理数据以生成单个字段,并以正确的顺序将值添加到该字段。应保持单个字段中的订单。这最好在外部管道中完成,您可以在其中查看源文档中的原始顺序。也许如果某些排序或其他逻辑可以从字段名称重建正确的顺序,您可以通过安装自定义UpdateRequestProcessorFactory
实现在Solr中完成。
答案 1 :(得分:1)
使用StatelessScriptUpdateProcessorFactory处理器有一个稳定的推荐选项。我们将使用Javascript按照我们需要的顺序获取所有字段和值。我将用一些步骤来写这个:
您的 schema.xml 将是相同的,除了架构不得有第三行(关于复制字段:* ... copyField源 _foo字段到allFoos字段.. 的)。这部分将委托给Javascript代码。它仍然是这样的:
<dynamicField name="`*_foo`" type="string" indexed="false" stored="true"/>
<field name="`allFoos`" type="string" indexed="true" stored="true" required="false" multiValued="true"/>
在核心的 solrconfig.xml 中,写下:
<!-- ... part of your solrconfig.xml ... -->
<requestHandler name="/update" class="solr.UpdateRequestHandler">
<lst name="defaults">
<str name="update.chain">custom</str>
</lst>
</requestHandler>
<!-- ... part of your solrconfig.xml ... -->
<updateRequestProcessorChain name="custom">
<processor class="solr.StatelessScriptUpdateProcessorFactory">
<str name="script">update-script.js</str>
<lst name="params">
<str name="config_param">example config parameter</str>
</lst>
</processor>
<processor class="solr.LogUpdateProcessorFactory" />
<processor class="solr.RunUpdateProcessorFactory" />
</updateRequestProcessorChain>
<!-- ... part of your solrconfig.xml ... -->
有了这个,我们告诉Solr使用链接插件'custom',一个自定义的URP(Update Request Processor),当你使用'update'时,它会使用 StatelessScriptUpdateProcessorFactory 处理器请求处理程序如果您正在使用其他请求处理程序,请在所需的请求处理程序中设置它。
您必须在'conf'核心目录的同一级文件夹中有一个' update-script.js '文件,其中包含您需要的所有功能以及一些示例。
在此 update-script.js 文件的函数processAdd(cmd)中,写下:
doc = cmd.solrDoc; // org.apache.solr.common.SolrInputDocument
id = doc.getFieldValue("id");
logger.info("update-script#processAdd: id = " + id);
fieldNames = doc.getFieldNames().toArray();
for (var i = 0; i < fieldNames.length; i++) {
fieldValue = doc.getFieldValue(fieldName[i]);
doc.addField("allFoos", String(fieldValue.toString()));
}
这在Solr中的任何摄取/更新的字段数据之前处理(这部分执行委托在RunUpdateProcessorFactory上)。
全部完成。