最近,我们开始研究Solr部分索引更新。
用于全部和部分更新的API看起来相似。代替
doc.addField("location", "UK")
solrClient.add(doc)
你必须写
doc.addField("location", map("set", "Germany"))
solrClient.add(doc)
我期望发生的事情:solr将为字段“ location”更新倒排索引
实际发生的情况:
结果,所有未存储的字段都将丢失。
我在邮件列表中发现了一些旧讨论,有人说这是预期的行为,您需要存储所有字段,依此类推。我们不想存储所有字段。“存储的”属性设计用于需要从Solr响应到调用者的情况下返回的字段。我们只需要较小的元信息作为响应,从而使存储的所有字段看起来像是一种过大的杀伤力。
问题是-为什么solr / lucene执行所有这些步骤来执行部分更新?据我了解,每个字段在其自己的文件中都有自己的反向索引,因此应该可以独立更新字段。从实际发生的情况来看,solr / lucene无法更新单个字段的索引,而我也找不到原因。
关于此主题的讨论:
您的观察是正确的-这就是行为。原因是某些因素可能取决于其他字段(copyField
例如,通过指令),如何合并字段(位置增量等),这就是为什么只能对存储的字段进行部分更新的原因-文档只需加载,就可以处理该特定字段的值,然后再次为其建立索引。
字段的索引没有自己的文件-完整索引的文件是一组文件,并且仅附加了索引-文档未在该索引中就地更改(因此文档仅标记为已删除,并且然后将新文档添加到索引)。当您optimize
在索引上运行时,索引将被重写而没有已删除的文档。
有解决的办法,而如果你的领域填补了一系列的条件,一个就地更新,可以代替执行的。这就是您要的。
就地更新与原子更新非常相似。从某种意义上讲,这是原子更新的子集。在常规的原子更新中,整个文件在应用更新期间会在内部重新编制索引。但是,在这种方法中,只有要更新的字段会受到影响,而其余文档不会在内部重新编制索引。因此,就地更新的效率不受更新的文档大小(即字段数,字段大小等)的影响。除了这些内部差异之外,原子更新和就地更新之间没有功能上的差异。
但是,这些要求可能与您的用例不匹配-即它们必须是非索引的并且是数字的(因为要替换的是后台的docValue,而不是索引的内容-通常无法执行此操作-索引仅附加):
仅当要更新的字段满足以下三个条件时,才使用此方法执行原子更新操作:
- 是非索引(indexed =“ false”),非存储(stored =“ false”),单值(multiValued =“ false”)数字docValues(docValues =“ true”)字段;
- 所述版本字段也是非索引,非存储单值docValues字段; 和,
- 更新字段的复制目标(如果有)也是非索引,未存储的单值数字docValues字段。
要使用就地更新,请在需要更新的字段中添加修饰符。内容可以更新或增量增加。