solr数据操作

本文介绍solr的基本数据操作,基于solr 8.2。solr支持多种数据格式,包括XML,JSON,CSV等,并提供多种脚本和工具来操作数据。本文讲解curl请求和JSON数据格式的处理方式。

本文使用单solr服务来演示数据操作,创建名为 my_core 的solr core, 文档schema如下:

<schema name="my" version="1.0">
  <uniqueKey>id</uniqueKey>
  <fieldType name="string" class="solr.StrField" sortMissingLast="true"/>
  <field name="id" type="string" multiValued="false" indexed="true" required="true" stored="true"/>
  <field name="author" type="string" multiValued="false" indexed="true" required="true" stored="true"/>
  <field name="title" type="string" indexed="true" required="true" stored="true" multiValued="false"/>
  <field name="tags" type="string" multiValued="true" indexed="true" stored="true"/>
</schema>

插入文档

插入单个文档

最基本的数据操作就是插入单个文档:

curl -X POST -H 'Content-Type: application/json' 'http://localhost:8983/solr/my_core/update/json/docs?commit=true' --data-binary '
{
  "id": "0132350882",
  "author": "Robert C. Martin",
  "title": "Clean Code: A Handbook of Agile Software Craftsmanship",
  "tags": [
    "Computer Programming Languages",
    "Software Testing",
    "Software Design & Engineering"
  ]
}'

参数说明:

  1. -X POST : 设置HTTP请求类型为POST,后续所有操作都为POST请求
  2. -H 'Content-Type: application/json' : 设置请求格式为JSON
  3. http://localhost:8983/solr/my_core/update/json/docs?commit=true: 请求地址URL和查询参数。其中 http://localhost:8983 为solr服务的地址和端口, my_core 为文档插入的core名称,可以根据自己的实际情况调整。 comment=true 参数表示此操作要进行同步提交。如果不设置此参数, solr则会根据 solrconfig.xml 文件 UpdateHandler 配置荐中的 autoCommit 配置延迟提交修改。
  4. --data-binary :此参数指定操作所需的JSON数据,这里是新插入的文档。

以上curl命令的几个参数在后续的操作中都会用到,用法也基本相同。

错误信息

当操作有误时,solr的响应体会包含错误信息。比如,当执行以下操作时:

curl -X POST -H 'Content-Type: application/json' 'http://localhost:8983/solr/my_core/update/json/docs' --data-binary '
{
  "id": "0132350882",
  "title": "Clean Code: A Handbook of Agile Software Craftsmanship"
}'

因为请求的JSON数据缺少了必需的字段 author ,solr会返回以下的错误信息:

{
  "responseHeader":{
    "status":400,
    "QTime":6},
  "error":{
    "metadata":[
      "error-class","org.apache.solr.common.SolrException",
      "root-error-class","org.apache.solr.common.SolrException"],
    "msg":"[doc=0132350882] missing required field: author",
    "code":400}}

此时,可以根据信息中的 msg 字段以及solr的日志来排查问题所在。后续其他操作的错误信息也会遵循类似的行为。

插入多个文档

如果希望在同一个请求入插入多个文档,只需要将文档数据以JSON数组的组织即可:

curl -X POST -H 'Content-Type: application/json' 'http://localhost:8983/solr/my_core/update/json/docs?commit=true' --data-binary '
[
  {
    "id": "0132350882",
    "author": "Robert C. Martin",
    "title": "Clean Code: A Handbook of Agile Software Craftsmanship",
    "tags": [
      "Computer Programming Languages",
      "Software Testing",
      "Software Design & Engineering"
    ]
  },
  {
    "id": "0201633612",
    "author": "Erich Gamma",
    "title": "Design Patterns: Elements of Reusable Object-Oriented Software",
    "tags": [
        "Object-Oriented Design",
        "Software Reuse",
        "Object-Oriented Software Design"
    ]
  }
]'

修改文档

覆写现有文档

修改文档的一种方式是使用solr的JSON命令接口来覆写现有的文档。比如在按照前文中的例子插入文档 0132350882 后,执行:

curl -X POST -H 'Content-Type: application/json' 'http://localhost:8983/solr/my_core/update?commit=true' --data-binary '
{
  "add": {
    "doc": {
      "id": "0132350882",
      "author": "Robert C. Martin",
      "title": "Clean Code"
    }
  }
}'

此操作和之前的插入操作有以下不同:

  1. 请求路径变为 /solr/my_core/update ,而不是 /solr/my_core/update/json/docs
  2. 请求体中的JSON需要 add 节点来表示操作类型。 add 节点下的 doc 子节点是需要修改的文档。add 下还可以添加其他节点,来指定操作的其他参数,比如 overwrite 。这里不再展开。

solr会根据schema中配置的主键来查询已有的文档记录,这里是 id,并用 doc 节点的内容覆写已有文档,所以 doc 节点需要给出完成的文档内容,没有出现在 doc 节点中的属性会从文档中删除。在这此例中,执行完操作后,文档 0132350882title 属性会被修改,而 tags 属性则会被删除。

注意到此JSON命令中的类型是 add 而不是 update , 因而当 doc 的主键没有对应记录存在时, solr会将 doc 内容作为一条新记录插入:

curl -X POST -H 'Content-Type: application/json' 'http://localhost:8983/solr/my_core/update?commit=true' --data-binary '
{
  "add": {
    "doc": {
      "id": "0134685997",
      "author": "Joshua Bloch",
      "title": "Effective Java"
    }
  }
}'

当这条操作执行完后,会新增一条文档 0134685997

进一步的,当此JSON命令中如果存在多个 add 节点,则可以同时对多条文档记录进行覆写操作。

原子更新(atomic update)

solr还提供另外一种修改文档的方式,原子修改(atomic update)。这种方式可以修改文档中指定的字段,而不需要提供完整的文档对象。

使用原子更新,solr core的配置需要满足以下条件

  1. schema中包含 _version_字段
  2. solrconfig.xml 配置文件中包含 updateLog 配置项

这里,我们将 schema.xml 文件调整为:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Solr managed schema - automatically generated - DO NOT EDIT -->
<schema name="my" version="1.0">
  <uniqueKey>id</uniqueKey>
  <fieldType name="string" class="solr.StrField" sortMissingLast="true"/>
  <fieldType name="long" class="solr.LongPointField" omitNorms="true"/>
  <field name="_version_" type="long" indexed="true" stored="true" multiValued="false"/>
  <field name="author" type="string" multiValued="false" indexed="true" required="true" stored="true"/>
  <field name="title" type="string" indexed="true" required="true" stored="true" multiValued="false"/>
  <field name="id" type="string" multiValued="false" indexed="true" required="true" stored="true"/>
  <field name="tags" type="string" multiValued="true" indexed="true" stored="true"/>
</schema>

solrconfig.xml 文件中添加 updateHandlerupdateLog 配置项:

<config>
  <luceneMatchVersion>8.2.0</luceneMatchVersion>
  <updateHandler>
    <updateLog>
      <str name="dir">${solr.ulog.dir:}</str>
    </updateLog>
  </updateHandler>
</config>

原子更新提供多种操作,这里演示设置一个字段,向一个数组类型的字段添加和删除元素的操作:

curl -X POST -H 'Content-Type: application/json' 'http://localhost:8983/solr/my_core/update?commit=true' --data-binary '
[
  {
    "id": "0132350882",
    "title": { "set": "Clean Code" },
    "tags": {
      "add": "Computer Science",
      "remove": "Software Testing"
    }
  }
]'

注意,无论是要修改一个还是多个文档,JSON数据的根节点都必须是一个数组,否则solr会当作覆写操作来解析。 id 用来定位要修改的文档。 title节点中的 set 表示将title字段修改为指定值。 tags 节点有两个操作, addremove ,分别表示将 Computer Science 元素添加到 tags 数组中,将 Software Testing 元素从 tags 数组中删除。此例中addremove 对应的值是单个元素,它们也可以接受数组值,用来表示同时插入或者删除多个值。

删除文档

根据主键删除文档

删除文档的基本方式是根据文档主键删除指定文档:

curl -X POST -H 'Content-Type: application/json' 'http://localhost:8983/solr/my_core/update?commit=true' --data-binary '
{
  "delete": { "id": "0132350882" }
}'

id节点的值可以也可以是一个数组,用来指定多个要删除的文档主键。注意,这里只能使用主键字段,而不能使用其他字段来匹配要删除的文档。

根据查询条件删除文档

如果需要根据查询条件删除所有的匹配文档,通过 query 来指定匹配条件。比如要删除所有 tags 中含有 Computer Programming Languages 的文档:

curl -X POST -H 'Content-Type: application/json' 'http://localhost:8983/solr/my_core/update?commit=true' --data-binary '
{
  "delete": { "query": "tags:\"Computer Programming Languages\"" }
}'

以下请求则会删除所有的文档:

curl -X POST -H 'Content-Type: application/json' 'http://localhost:8983/solr/my_core/update?commit=true' --data-binary '
{
  "delete": { "query": "*:*" }
}'

数据导出和还原

solr提供数据快照功能来实现数据的导出和还原。

数据导出

通过类似以下请求来创建一个数据快照:

curl 'http://localhost:8983/solr/my_core/replication?command=backup'

这个请求比前文中的其他请求都要简单,而且这里使用的是GET请求。实际上GET和POST请求都是可以的。

这个请求只是触发了创建快照的操作,而不会同步等待快照创建完成。当数据比较多的时候,快照可能会需要比较长的时间才能完成。此时,可以通过以下请求来查看快照创建的处理状态:

curl 'http://localhost:8983/solr/my_core/replication?command=details'

同样的,使用GET或者POST请求的效果是相同的。

solr在收到创建快照请求后,会在core的数据目录下创建一个名为 snapshot.<yyyyMMddHHmmssSSS> 目录,用来保存快照数据。比如在 /var/solr/data/my_core/data 目录下会有类似 snapshot.20191203092949307 这样快照目录。

数据恢复

有了数据快照之后,就可以将数据恢复到快照保存的状态了。

执行类似以下操作就可以恢复数据:

curl  'http://localhost:8983/solr/my_core/replication?command=restore'

同样,恢复操作也是异步的,可以通过以下操作来查看恢复操作的状态:

curl 'http://localhost:8983/solr/my_core/replication?command=restorestatus'

solr在收到数据恢复请求之后,会在core的数据目录下查找命名格式为 snapshot.<yyyyMMddHHmmssSSS> 的目录,然后使用目录名后缀的时间最大的快照来进行数据恢复。

参考文档

此文中只简单介绍了solr数据的基本操作,这些操作还有很多其他的参数和用法,而且还有很多其他的操作。这些操作可以参考solr的官方文档。文中的例子是基于solr 8.2版本的,最新版本的solr的操作会有不同,下面列出的都是solr 8.2的文档。

posted @ 2019-12-03 18:01  不写日记  阅读(1089)  评论(0编辑  收藏  举报