一旦索引了solr索引中所需的内容,您将要开始考虑处理这些文档更改的策略。SOLR支持三种更新仅部分更改的文档的方法。
第一个是原子更新。这种方法只允许更改文档的一个或多个字段,而不必重新索引整个文档。
第二种方法称为就地更新。这种方法类似于原子更新(从某种意义上说是原子更新的一个子集),但只能用于更新单值、非索引和非存储的基于docvalue的数字字段。
第三种方法称为乐观并发或乐观锁。它是许多NoSQL数据库的一个特性,允许根据文档的版本有条件地更新文档。这种方法包括如何处理版本匹配或错误匹配的语义和规则。
原子更新(和就地更新)和乐观并发可以用作管理文档更改的独立策略,也可以组合使用:可以使用乐观并发有条件地应用原子更新。
原子更新
solr支持几个自动更新文档值的修饰符。这只允许更新特定的字段,这有助于在索引添加速度对应用程序至关重要的环境中加快索引过程。
要使用原子更新,请向需要更新的字段添加一个修饰符。如果字段具有数字类型,则可以更新、添加或增量增加内容。
set
使用指定的值设置或替换字段值,或者如果将“null”或空列表指定为新值,则删除这些值。
可以指定为单个值,也可以指定为多值字段的列表。
add
将指定的值添加到多值字段。可以指定为单个值,也可以指定为列表。
add-distinct
将指定的值添加到多值字段中(仅当尚未存在时)。可以指定为单个值,也可以指定为列表。
remove
从多值字段中删除(所有出现的)指定值。可以指定为单个值,也可以指定为列表。
removeregex
从多值字段中删除指定regex的所有出现项。可以指定为单个值,也可以指定为列表。
inc
以特定的量递增一个数值。必须指定为单个数值。
Field Storage
原子更新文档的核心功能要求架构中的所有字段必须配置为存储(stored=“true”)或docvalues(docvalues=“true”),但目标为
如果将
还必须设置其他类型的派生字段,以便不存储它们。一些空间字段类型(如bboxfield和latlontype)使用派生字段。currencyFieldType还使用派生字段。这些类型创建通常由动态字段定义指定的其他字段。不能存储该动态字段定义,否则索引将失败。
例子:
如果以下document存在于我们的集合中:
{"id":"mydoc",
"price":10,
"popularity":42,
"categories":["kids"],
"sub_categories":["under_5","under_10"],
"promo_ids":["a123x"],
"tags":["free_to_try","buy_now","clearance","on_sale"]
}
我们应用以下更新命令:
{"id":"mydoc",
"price":{"set":99},
"popularity":{"inc":20},
"categories":{"add":["toys","games"]},
"sub_categories":{"add-distinct":"under_10"},
"promo_ids":{"remove":"a123x"},
"tags":{"remove":["free_to_try","on_sale"]}
}
结果文档是:
{"id":"mydoc",
"price":99,
"popularity":62,
"categories":["kids","toys","games"],
"sub_categories":["under_5","under_10"],
"tags":["buy_now","clearance"]
}
就地更新
就地更新与原子更新非常相似;在某种意义上,这是原子更新的一个子集。在常规的原子更新中,整个文档在应用更新期间会在内部重新索引。但是,在这种方法中,只有要更新的字段会受到影响,其余的文档不会在内部重新索引。因此,就地更新的效率不受被更新的文档的大小(即,字段的数量、字段的大小等)的影响。除了这些内部差异之外,原子更新和就地更新之间没有功能差异。
只有当要更新的字段满足以下三个条件时,才使用此方法执行原子更新操作:
1、are non-indexed (indexed="false"), non-stored (stored="false"), single valued (multiValued="false") numeric docValues (docValues="true") fields;
2、the _version_ field is also a non-indexed, non-stored single valued docValues field; and,
3、copy targets of updated fields, if any, are also non-indexed, non-stored single valued numeric docValues fields.
要使用就地更新,请向需要更新的字段添加修改器。内容可以更新或增量增加。
set
用指定的值设置或替换字段值。可以指定为单个值。
inc
按特定数量递增数值。必须指定为单个数值。
就地更新示例
如果价格和流行度字段在模式中定义为:
如果以下document存在于我们的集合中:
{
"id":"mydoc",
"price":10,
"popularity":42,
"categories":["kids"],
"promo_ids":["a123x"],
"tags":["free_to_try","buy_now","clearance","on_sale"]
}
我们应用以下更新命令:
{
"id":"mydoc",
"price":{"set":99},
"popularity":{"inc":20}
}
结果文档是:
{
"id":"mydoc",
"price":99,
"popularity":62,
"categories":["kids"],
"promo_ids":["a123x"],
"tags":["free_to_try","buy_now","clearance","on_sale"]
}
乐观的并发控制
乐观并发是solr的一个特性,它可以被更新/替换文档的客户端应用程序使用,以确保它们正在替换/更新的文档没有被另一个客户端应用程序同时修改。此功能的工作原理是要求索引中的所有文档都有一个“版本”_version_ 字段,并将其与作为更新命令一部分指定的“版本”_version_ 进行比较。默认情况下,solr的模式包括一个版本字段_version_ ,该字段将自动添加到每个新文档中。
通常,使用乐观并发涉及以下工作流程:
当客户端将更改后的文档重新提交给solr时,可以在更新中包含_version_ ,以调用乐观并发控制。特定的语义用于定义何时应该更新文档或何时报告冲突。
如果正在更新的文档不包含版本字段,并且未使用原子更新,则该文档将按常规solr规则处理,这通常是为了放弃以前的版本。
使用乐观并发时,客户机可以包含可选的versions=true请求参数,以指示要添加的文档的新版本应包括在响应中。这允许客户立即知道添加的每个文档的版本,而无需发出冗余/获取请求。
以下是一些在查询中使用versions=true的示例:
$ curl -X POST -H 'Content-Type: application/json' 'http://localhost:8983/solr/techproducts/update?versions=true' --data-binary '[ { "id" : "aaa" }, { "id" : "bbb" } ]'
{"responseHeader":{"status":0,"QTime":6},
"adds":["aaa",1498562471222312960,
"bbb",1498562471225458688]}
在这个例子中,我们添加了2个文档“aaa”和“bbb”。因为我们在请求中添加了versions=true,所以响应会显示每个文档的文档版本。
$ curl -X POST -H 'Content-Type: application/json' 'http://localhost:8983/solr/techproducts/update?_version_=999999&versions=true' --data-binary '[{ "id" : "aaa", "foo_s" : "update attempt with wrong existing version" }]'
{"responseHeader":{"status":409,"QTime":3},
"error":{"msg":"version conflict for aaa expected=999999 actual=1498562471222312960",
"code":409}}
在本例中,我们试图更新文档“aaa”,但在请求中指定了错误的版本:version=999999与添加文档时获得的文档版本不匹配。我们得到了一个错误的响应。
$ curl -X POST -H 'Content-Type: application/json' 'http://localhost:8983/solr/techproducts/update?_version_=1498562471222312960&versions=true&commit=true' --data-binary '[{ "id" : "aaa", "foo_s" : "update attempt with correct existing version" }]'
{"responseHeader":{"status":0,"QTime":5},
"adds":["aaa",1498562624496861184]}
现在,我们已经发送了一个更新,其中包含与索引中的值匹配的版本值,并且成功了。因为我们将versions=true包含在更新请求中,所以响应中包含了一个不同的值。
$ curl 'http://localhost:8983/solr/techproducts/query?q=*:*&fl=id,_version_'
{
"responseHeader":{
"status":0,
"QTime":5,
"params":{
"fl":"id,_version_",
"q":"*:*"}},
"response":{"numFound":2,"start":0,"docs":[
{
"id":"bbb",
"_version_":1498562471225458688},
{
"id":"aaa",
"_version_":1498562624496861184}]
}}
最后,我们可以发出一个查询,请求在响应中包含“版本”字段,我们可以看到示例索引中的两个文档。
有关更多信息,请参见Yonik Seeley在Apache Lucene Eurocon 2012的Solr 4中关于NoSQL功能的演示。
以文档为中心的版本控制约束
乐观并发性非常强大,而且工作效率非常高,因为它使用内部分配的、全局唯一的值作为_version_字段。但是,在某些情况下,用户可能希望配置自己的文档特定版本字段,其中版本值由外部系统根据每个文档分配,并让SOLR拒绝尝试用“旧”版本替换文档的更新。在这种情况下,DocBasedVersionConstraintsProcessorFactory 可能很有用。
DocBasedVersionConstraintsProcessorFactory 的基本用法是在solrconfig.xml中将其配置为updateRequestProcessorChain的一部分,并在架构中指定在验证更新时应检查的自定义版本字段的名称:
注意,versionField是一个用逗号分隔的字段列表,用于检查版本号。配置后,此更新处理器将拒绝(HTTP错误代码409)任何更新现有文档的尝试,其中“新”文档中“my_version_l”字段的值不大于现有文档中该字段的值。
versionField与_version_
solr用于其正常乐观并发性的“_version_”字段在如何将更新分发到solrcloud中的副本中也具有重要的语义,并且必须由solr在内部分配。用户不能重新使用该字段并将其指定为在docbasedversionConstraintsProcessorFactory配置中使用的版本字段versionField。
DocbasedversionConstraintsProcessorFactory支持以下附加配置参数,这些参数都是可选的:
ignoreOldUpdates
默认为false的布尔选项。如果设置为真,更新将被静默忽略(并向客户端返回状态200),而不是拒绝版本字段过低的更新。
deleteVersionParam
A String parameter that can be specified to indicate that this processor should also inspect Delete By Id commands.
The value of this option should be the name of a request parameter that the processor will consider mandatory for all attempts to Delete By Id, and must be be used by clients to specify a value for the versionField which is greater then the existing value of the document to be deleted.
When using this request parameter, any Delete By Id command with a high enough document version number to succeed will be internally converted into an Add Document command that replaces the existing document with a new one which is empty except for the Unique Key and versionField to keeping a record of the deleted version so future Add Document commands will fail if their "new" version is not high enough.
If versionField is specified as a list, then this parameter too must be specified as a comma delimited list of the same size so that the parameters correspond with the fields.
supportMissingVersionOnOldDocs
此布尔参数默认为false,但如果设置为true,则允许覆盖在此功能启用之前写入的任何文档,并且这些文档缺少版本字段。
https://lucene.apache.org/solr/7_7_0//solr-core/org/apache/solr/update/processor/DocBasedVersionConstraintsProcessorFactory.html
https://gitbox.apache.org/repos/asf?p=lucene-solr.git;a=blob;f=solr/core/src/test-files/solr/collection1/conf/solrconfig-externalversionconstraint.xml;hb=HEAD
原地址:http://lucene.apache.org/solr/guide/7_7/updating-parts-of-documents.html