本文介紹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"
]
}'
參數說明:
-X POST
: 設置HTTP請求類型為POST,后續所有操作都為POST請求-H 'Content-Type: application/json'
: 設置請求格式為JSONhttp://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
配置延遲提交修改。--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"
}
}
}'
此操作和之前的插入操作有以下不同:
- 請求路徑變為
/solr/my_core/update
,而不是/solr/my_core/update/json/docs
- 請求體中的JSON需要
add
節點來表示操作類型。add
節點下的doc
子節點是需要修改的文檔。add
下還可以添加其他節點,來指定操作的其他參數,比如overwrite
。這里不再展開。
solr會根據schema中配置的主鍵來查詢已有的文檔記錄,這里是 id
,並用 doc
節點的內容覆寫已有文檔,所以 doc
節點需要給出完成的文檔內容,沒有出現在 doc
節點中的屬性會從文檔中刪除。在這此例中,執行完操作后,文檔 0132350882 的 title 屬性會被修改,而 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的配置需要滿足以下條件
- schema中包含
_version_
字段 - 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 文件中添加 updateHandler
和 updateLog
配置項:
<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
節點有兩個操作, add
和 remove
,分別表示將 Computer Science
元素添加到 tags
數組中,將 Software Testing
元素從 tags
數組中刪除。此例中add
和 remove
對應的值是單個元素,它們也可以接受數組值,用來表示同時插入或者刪除多個值。
刪除文檔
根據主鍵刪除文檔
刪除文檔的基本方式是根據文檔主鍵刪除指定文檔:
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的文檔。