[Solr]同じ内容のドキュメントの重複を防ぐ(De-Duplication)

はじめに
Solrでは基本的にIDフィールドの値でドキュメントを区別しているため、IDが異なれば同じ内容のドキュメントでも別々にインデックスされます。同じ内容のドキュメントの重複を防ぎたい場合はDe-Duplicationの機能を利用します。
De-Duplication の設定
De-Duplication を利用するためには、updateRequestProcessorChain に SignatureUpdateProcessor を組み込みます。
ここでは例として大阪の施設情報を利用します。以下のような文書構造になっています。
[
{
"id": "官公庁!1",
"type": "官公庁",
"area": "住之江区",
"name": "軽自動車検査協会大阪主管事務所",
"address": "住之江区南港東3-4-62"
}
]
solrconfig.xml に以下を追加します。
<updateRequestProcessorChain name="dedupe">
<processor class="solr.processor.SignatureUpdateProcessorFactory">
<bool name="enabled">true</bool>
<str name="signatureField">signature</str>
<bool name="overwriteDupes">true</bool>
<str name="fields">type,name</str>
<str name="signatureClass">solr.processor.Lookup3Signature</str>
</processor>
<processor class="solr.LogUpdateProcessorFactory" />
<processor class="solr.RunUpdateProcessorFactory" />
</updateRequestProcessorChain>
<requestHandler name="/update" class="solr.UpdateRequestHandler" >
<lst name="defaults">
<str name="update.chain">dedupe</str>
</lst>
</requestHandler>
SignatureUpdateProcessor は、指定されたフィールドのハッシュ値を計算して一致すれば同一ドキュメントとみなすという動きになります。以下の3種類から選んで signatureClass プロパティで指定します。
- MD5Signature
- 128ビットのハッシュ
- Lookup3Signature
- 64ビットのハッシュ。MD5Signatureよりも高速
- TextProfileSignature
- 多少の曖昧さを許す
fieldsプロパティで、どのフィールドが同じなら同一のドキュメントとみなすかを指定します。
上の例では type と name が同一なら同じドキュメントとしました。
signatureField はハッシュ値を格納するフィールドを指定するものです。
overwriteDupes をtrue に設定すると、ドキュメントが同一と判定された場合に新しい方で古い方を上書きします。
実行例
上記の設定をした状態で以下のドキュメントをインデックスします。
[
{
"id": "官公庁!1",
"type": "官公庁",
"area": "住之江区",
"name": "軽自動車検査協会大阪主管事務所",
"address": "住之江区南港東3-4-62"
}
]
検索結果は以下の通りです。signature フィールドが自動的に付与されています。
{
"response":{"numFound":1,"start":0,"numFoundExact":true,"docs":[
{
"id":"官公庁!1",
"type":"官公庁",
"area":"住之江区",
"name":"軽自動車検査協会大阪主管事務所",
"address":"住之江区南港東3-4-62",
"signature":"e3e630e5c046e6d3",
"_version_":1701175515816132608}]
}}
次に以下のドキュメントをインデックスします。名前と種別は同じで住所が変更になったという設定です。
[
{
"id": "官公庁!2",
"type": "官公庁",
"area": "港区",
"name": "軽自動車検査協会大阪主管事務所",
"address": "港区築港4-10-3"
}
]
2番目のドキュメントをインデックスした後の検索結果は以下の通りです。
{
"response":{"numFound":1,"start":0,"numFoundExact":true,"docs":[
{
"id":"官公庁!2",
"type":"官公庁",
"area":"港区",
"name":"軽自動車検査協会大阪主管事務所",
"address":"港区築港4-10-3",
"signature":"e3e630e5c046e6d3",
"_version_":1701175675284619264}]
}}
期待通り上書きされています。idも新しいものになっています。
ちなみに、overwriteDupes = false で設定した場合には以下のようになりました。
{
"response":{"numFound":2,"start":0,"numFoundExact":true,"docs":[
{
"id":"官公庁!1",
"type":"官公庁",
"area":"住之江区",
"name":"軽自動車検査協会大阪主管事務所",
"address":"住之江区南港東3-4-62",
"signature":"e3e630e5c046e6d3",
"_version_":1701175515816132608},
{
"id":"官公庁!2",
"type":"官公庁",
"area":"港区",
"name":"軽自動車検査協会大阪主管事務所",
"address":"港区築港4-10-3",
"signature":"e3e630e5c046e6d3",
"_version_":1701175519813304320}]
}}
「上書きしない」というのは古い方のドキュメントがそのまま残るのかと思っていましたが、同じシグネチャのドキュメントが重複してインデックスされるということでした。