Data Import Handler – usuwanie danych z indeksu

Usuwanie danych z indeksu przy wykorzystaniu indeksowania przyrostowego w DIH jest na wiki SOLR potraktowane szczątkowo, jako coś, co działa analogicznie do aktualizacji rekordów. Podobnie we wcześniejszym artykule użyłem tego skrótu, tym bardziej, że podany przeze mnie przykład z indeksowaniem zasobów wikipedii nie potrzebował usuwania danych.

Mając pod ręką przykładowe dane z albumami i wykonawcami postanowiłem pokazać mój sposób postępowania w takich wypadkach. Dla uproszczenia i przejrzystości zakładam, że po pierwszym zaimportowaniu, danych może tylko ubywać.

Dane testowe

Moje dane testowe mieszczą się bazie PostgreSQL w tabeli zdefiniowanej następująco:

Table "public.albums"
Column |  Type   |                      Modifiers
--------+---------+-----------------------------------------------------
id     | integer | not null default nextval('albums_id_seq'::regclass)
name   | text    | not null
author | text    | not null
Indexes:
"albums_pk" PRIMARY KEY, btree (id)

W tabeli znajduje się 825661 rekordów.

Instalacja testowa

Do testów użyłem instancji SOLR posiadającej następującą charakterystykę:

Definicja w schema.xml:

<fields>
<field name="id" type="string" indexed="true" stored="true" required="true" />
<field name="album" type="text" indexed="true" stored="true" multiValued="true"/>
<field name="author" type="text" indexed="true" stored="true" multiValued="true"/>
</fields>
<uniqueKey>id</uniqueKey>
<defaultSearchField>album</defaultSearchField>

Definicja DIH w solrconfig.xml:

<requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler">
<lst name="defaults">
<str name="config">db-data-config.xml</str>
</lst>
</requestHandler>

I plik DIH db-data-config.xml:

<dataConfig>
<dataSource driver="org.postgresql.Driver" url="jdbc:postgresql://localhost:5432/shardtest" user="solr" password="secret" />
<document>
<entity name="album" query="SELECT * from albums">
<field column="id" name="id" />
<field column="name" name="album" />
<field column="author" name="author" />
</entity>
</document>
</dataConfig>

Przed naszym testem zaimportowałem wszystkie dane z tabeli albums.

Usuwanie danych

Patrząc na tabelę widać, że gdy usuniemy rekord, ginie on bez śladu i jedynym sposobem aktualizacji naszego indeksu byłoby porównanie identyfikatorów dokumentów w indeksie z identyfikatorami w bazie i wyrzucenie tych, które w bazie już nie istnieją. Wolne i niewygodne. Innym sposobem jest dodatnie kolumny deleted_at: zamiast kasowania fizycznie rekordu, uzupełniamy tylko tę kolumnę. DIH może wtedy pobrać wszystkie rekordy z ustawioną datą późniejszą od ostatniego indeksowania. Wadą tego rozwiązania może by konieczność modyfikacji aplikacji by uwzględniały tak „skasowane” rekordy.

Ja zastosuje inne rozwiązanie, przeźroczyste dla aplikacji. Tworzymy nową tabelę:

CREATE TABLE deletes
(
id serial NOT NULL,
deleted_id bigint,
deleted_at timestamp without time zone NOT NULL,
CONSTRAINT deletes_pk PRIMARY KEY (id)
);

Do tej tabeli automagicznie będziemy dopisywać identyfikatory tych elementów, które zostały usunięte z tabeli albums oraz informacje kiedy zostały usunięte.

Teraz dodamy jeszcze funkcję:

CREATE OR REPLACE FUNCTION insert_after_delete()
RETURNS trigger AS
$BODY$BEGIN
IF tg_op = 'DELETE' THEN
INSERT INTO deletes(deleted_id, deleted_at)
VALUES (old.id, now());
RETURN old;
END IF;
END$BODY$
LANGUAGE plpgsql VOLATILE;

oraz trigger:

CREATE TRIGGER deleted_trg
BEFORE DELETE
ON albums
FOR EACH ROW
EXECUTE PROCEDURE insert_after_delete();

Sprawdzamy działanie

Zgodnie z planem, każdy usunięty wpis w tabeli albums powinien skutkować uzupełnieniem tabeli
deletes. Sprawdźmy więc. Usuwamy parę rekordów:

=> DELETE FROM albums where id < 37;
DELETE 2
=> SELECT * from deletes;
id | deleted_id |         deleted_at
----+------------+----------------------------
26 |         35 | 2010-12-23 13:53:18.034612
27 |         36 | 2010-12-23 13:53:18.034612
(2 rows)

Czyli baza działa.

Uzupełniamy plik konfiguracyjny DIH tak, by entity było zdefiniowane następująco:

<entity name="album" query="SELECT * from albums"
  deletedPkQuery="SELECT deleted_id as id FROM deletes WHERE deleted_at > '$'{dataimporter.last_index_time}'">

Dzięki temu przy imporcie przyrostowym DIH użyje atrybutu deletedPkQuery by pobrać identyfikatory tych dokumentów, które należy usunąć.

Sprytny czytelnik pewnie zacznie się zastanawiać, czy na pewno potrzebna jest nam kolumna z datą usunięcia rekordu. Przecież możemy usunąć wszystkie rekordy znalezione w tabeli deleted a następnie skasować zawartość tej tabeli. Teoretycznie to prawda, ale w przypadku problemu z serwerem indeksującym SOLR w naszym wypadku łatwo zastąpić go innym – jego stopień synchronizacji z bazą nie jest bardzo istotny – po prostu za następnym importem przyrostowym nastąpi synchronizacja z bazą. W opcji z kasowaniem zawartości deletes takie możliwości nie ma.

Wykonujemy teraz import przyrostowy wywołując adres: /solr/dataimport?command=delta-import
W logach powinna pojawić się linia podobna do tej:
INFO: {delete=[35, 36],optimize=} 0 2
Co oznacza, że DIH poprawnie usunął z indeksu te dokumenty, które usunęliśmy wcześniej z bazy.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

We use cookies to personalise content and ads, to provide social media features and to analyse our traffic. We also share information about your use of our site with our social media, advertising and analytics partners. /home/aludstro/domains/solr.pl/public_html/wp-includes/link-template.php on line 409
https://solr.pl/data-import-handler-usuwanie-danych-z-indeksu/">View more
Cookies settings
Accept
Privacy & Cookie policy
Privacy & Cookies policy
Cookie name Active
Save settings
Cookies settings