Reports auf Alfresco
Die Frage kam im Alfresco Discord Channel auf: Wie kann man auswerten, wieviel Speicherplatz durch Dokumentversionen in Alfresco belegt werden?
Alfresco speichert alle Informationen zu Dokumenten in einer relationalen Datenbank. Allerdings sind diese Daten stark normalisiert und für fachliche Auswertungen nicht ganz so einfach zu nutzen. Um effizientes Reporting zu betreiben, empfielt es sich daher, die gewünschten Daten per Event in eigenen Datenbanktabellen zu sammeln, damit diese einfach ausgewertet werden können. Hierfür muss man ein entsprechendes Behavior in Java entwickeln, welches bei den zu registrierenden Events (z.B. bei Erstellung, Update, Delete) Einträge in einer Reporting-Tabelle erstellt. Dies bedeutet allerdings auch, dass man bereits vorher wissen muss, was man auswerten will. Was macht man allerdings, wenn man solche Daten nicht gesammelt hat?
Wenn man das Datenbank-Modell des Alfresco-Repository versteht, ist es trotz Normalisierung möglich, viele der gewünschten Abfragen direkt auf der Datenbank auszuführen. Je nach Anzahl der im Alfresco gespeicherten Daten muss dies allerdings mit Vorsicht genutzt werden, da während der Auswertung sehr grosse Datenmengen kombiniert und ausgewertet werden müssen. Es kann daher sinnvoll sein, die nachfolgende Abfrage in Teilschritte aufzuteilen und die Zwischenergebnisse in neuen Tabellen zwischen zu speichern. In Postgres lässt sich dies sogar in sogenannten materialized views cachen und enorm beschleunigen.
Datenbank Query
SELECT
n.id AS node_id,
concat(s.protocol,'://',s.identifier,'/',n.uuid) AS node_ref,
nnp.string_value AS file_name,
sum(u.content_size) AS sum_kb_versions
FROM alf_node n
JOIN alf_store s ON (n.store_id=s.id AND s.protocol='workspace' AND s.identifier='SpacesStore')
-- find name prop
join alf_node_properties nnp ON (
nnp.node_id=n.id AND
nnp.qname_id = (SELECT id FROM alf_qname WHERE local_name='name' AND ns_id IN (SELECT id FROM alf_namespace WHERE uri='http://www.alfresco.org/model/content/1.0'))
)
-- filter nodes having version > 1.0
join alf_node_properties p1 ON (p1.node_id=n.id
AND p1.qname_id = (SELECT id FROM alf_qname WHERE local_name='versionLabel' AND ns_id IN (SELECT id FROM alf_namespace WHERE uri='http://www.alfresco.org/model/content/1.0'))
AND p1.string_value!='1.0'
)
-- find version nodes having the same nodeRef as 'frozenNodeRef' property
join alf_node_properties vnp ON (
vnp.qname_id = (SELECT id FROM alf_qname WHERE local_name='frozenNodeRef' AND ns_id = (SELECT id FROM alf_namespace WHERE uri='http://www.alfresco.org/model/versionstore/2.0'))
AND concat('workspace://SpacesStore/',n.uuid) = vnp.string_value
)
-- also filter version nodes > 1.0
JOIN alf_node_properties vvnp ON (
vnp.node_id = vvnp.node_id AND
vvnp.qname_id=(SELECT id FROM alf_qname WHERE local_name='versionLabel' AND ns_id IN (SELECT id FROM alf_namespace WHERE uri='http://www.alfresco.org/model/versionstore/2.0')) and
vvnp.string_value!='1.0'
)
-- find content id of the version node
join alf_node_properties cnp ON (
vnp.node_id=cnp.node_id AND
cnp.qname_id = (SELECT id FROM alf_qname WHERE local_name='content' AND ns_id IN (SELECT id FROM alf_namespace WHERE uri='http://www.alfresco.org/model/content/1.0'))
)
JOIN alf_content_data d ON (cnp.long_value=d.id)
JOIN alf_content_url u ON (d.content_url_id=u.id)
-- group version sizes by node
GROUP BY n.id, nnp.string_value, s.protocol, s.identifier
Bildnachweis Titelbild: aitoff (Andrew Martin) lizensiert unter der pixabay license (free for commercial use)