Posts Tagged ‘ezpublish’

Manuell databasfråga i eZ Publish, för ökad prestanda

tisdag, januari 24th, 2012

eZ Publish är ett mycket kompetent system för innehållshantering, men ibland kan man behöva gå förbi alla praktiska funktioner som finns. Bland annat kan det vara aktuellt att göra detta när man vill lista en stor mängd data i tabellform, till exempel en medlemslista. Vi hade ett projekt där kunden ville att ungefär 900 medlemmar skulle visas samtidigt i en lista, samt på en Googlekarta, vilket gjorde att det inte blev riktigt optimalt att använda de befintliga funktionerna i eZ Publish, det gick helt enkelt för långsamt. För att lösa problemet byggde jag en modul med en custom fetch som tog hand om det hela istället för de inbyggda fetch-funktionerna. Hur man bygger en egen modul finns väl dokumenterat och det är inget jag tänker beskriva nu, däremot fanns det väldigt lite information (i princip obefintlig) om hur man hämtar ut information direkt ur databasen. Genom att studera databasen och med hjälp av lite reverse enginering kom jag fram till följande.

Om man utgår från tabellen ezcontentobject_tree som representerar nodträdet så kan man köra en sql-fråga för att få fram alla barn till en viss nod.

SELECT et.contentobject_id id
FROM   ezcontentobject_tree et
WHERE  et.parent_node_id = 2

Satsen ovan ger följande resultat.

+------+
| id   |
+------+
|   58 |
|   59 |
|   76 |
|  122 |
+------+

Alltså, en lista på de objekt-id’n som finns direkt under noden med id 2.

Information om varje objekt lagras i tabellen ezcontentobject_attribute, därför gör man en JOIN för att få ut även denna information. Satsen blir då så här.

SELECT et.contentobject_id id,
       en.data_text        namn
FROM   ezcontentobject_tree et
       LEFT JOIN ezcontentobject_attribute en
         ON et.contentobject_id = en.contentobject_id
            AND et.contentobject_version = en.version
            AND en.contentclassattribute_id = 361
WHERE  et.parent_node_id = 97
       AND et.contentobject_is_published = 1
       AND et.is_hidden = 0
       AND et.is_invisible = 0

Här hämtas alltså information från tabellen ezcontentobject_attribute med contentclassattribut_id lika med 361, vilket är objektets namn i detta fall. Detta id hittar man i administrationsgränssnittet under Setup->Classes och sedan den klass objektet är en instans av. Se bilden nedan.

Jag har i satsen ovan lagt  till tre villkor i slutet som ser till att man bara får träffar på noder som är publicerade och synliga på sajten.

Resultatet blir.

+------+-----------------------------+
| id   | namn                        |
+------+-----------------------------+
|  398 | COOP OBS! LILLESTRØM        |
|  399 | COOP OBS! LØREN             |
|  400 | COOP OBS! MARIERO           |
|  401 | COOP OBS! MORENEN           |
|  402 | COOP OBS! NORD AVD. HARSTAD |
+------+-----------------------------+

För varje attribut man vill hämta ut måste man alltså göra en extra JOIN enligt ovan.

Om man vill hämta attribut av typen ezurl måste man göra två extra JOINs eftersom själva urlen sparas i tabellen ezurl och korskopplas i tabellen ezurl_object_link. Det man måste lägga till är alltså.

LEFT JOIN ezcontentobject_attribute eu
  ON et.contentobject_id = eu.contentobject_id
     AND et.contentobject_version = eu.version
     AND eu.contentclassattribute_id = 367
LEFT JOIN ezurl_object_link eol
  ON eu.id = eol.contentobject_attribute_id
     AND eu.version = eol.contentobject_attribute_version
LEFT JOIN ezurl eurl
  ON eol.url_id = eurl.id

Den kompletta sql-frågan blev så här.


SELECT et.contentobject_id id,
       en.data_text        name,
       etel.data_text      tele,
       efa.data_text       fax,
       pnr.data_text       postnr,
       por.data_text       postort,
       em.data_text        email,
       eurl.url            url
FROM   ezcontentobject_tree et
       LEFT JOIN ezcontentobject_attribute en
         ON et.contentobject_id = en.contentobject_id
            AND et.contentobject_version = en.version
            AND en.contentclassattribute_id = 361
       LEFT JOIN ezcontentobject_attribute etel
         ON et.contentobject_id = etel.contentobject_id
            AND et.contentobject_version = etel.version
            AND etel.contentclassattribute_id = 362
       LEFT JOIN ezcontentobject_attribute efa
         ON et.contentobject_id = efa.contentobject_id
            AND et.contentobject_version = efa.version
            AND efa.contentclassattribute_id = 363
       LEFT JOIN ezcontentobject_attribute pnr
         ON et.contentobject_id = pnr.contentobject_id
            AND et.contentobject_version = pnr.version
            AND pnr.contentclassattribute_id = 364
       LEFT JOIN ezcontentobject_attribute por
         ON et.contentobject_id = por.contentobject_id
            AND et.contentobject_version = por.version
            AND por.contentclassattribute_id = 365
       LEFT JOIN ezcontentobject_attribute em
         ON et.contentobject_id = em.contentobject_id
            AND et.contentobject_version = em.version
            AND em.contentclassattribute_id = 366
       LEFT JOIN ezcontentobject_attribute eu
         ON et.contentobject_id = eu.contentobject_id
            AND et.contentobject_version = eu.version
            AND eu.contentclassattribute_id = 367
       LEFT JOIN ezurl_object_link eol
         ON eu.id = eol.contentobject_attribute_id
            AND eu.version = eol.contentobject_attribute_version
       LEFT JOIN ezurl eurl
         ON eol.url_id = eurl.id
WHERE  et.parent_node_id = 97
       AND et.contentobject_is_published = 1
       AND et.is_hidden = 0
       AND et.is_invisible = 0

Resultatet av frågan blir.

+------+-----------------------------+-------------+-------------+--------+------------+------------------------------+------+
| id   | name                        | tele        | fax         | postnr | postort    | email                        | url  |
+------+-----------------------------+-------------+-------------+--------+------------+------------------------------+------+
|  398 | COOP OBS! LILLESTRØM        | 63 80 55 00 | 63 81 38 30 | 2000   | LILLESTRØM | xxxxx.xxxxx@obs.coop.no      | NULL |
|  399 | COOP OBS! LØREN             | 22 65 50 65 | 22 64 57 17 | 0513   | OSLO       | xxx.xxx.xxx.xxx@obs.coop.no  | NULL |
|  400 | COOP OBS! MARIERO           | 51 82 50 50 | 51 82 50 51 | 4095   | STAVANGER  | xxxx.xxxxxxx@obs.coop.no     | NULL |
|  401 | COOP OBS! MORENEN           | 69 84 65 00 | 69 84 65 51 | 1859   | SLITU      | xxxxxx.xxxxxxx@obs.coop.no   | NULL |
|  402 | COOP OBS! NORD AVD. HARSTAD | 77 02 89 00 | 77 02 89 01 | 9406   | HARSTAD    | xxxxxx.xxxxxx.x@nord.coop.no | NULL |
+------+-----------------------------+-------------+-------------+--------+------------+------------------------------+------+

Den här datan använde vi sedan för att bygga en lista över medlemmarna. Vi valde dessutom att generera html-koden direkt i modulen eftersom vi fortfarande inte var helt nöjda med prestandan när vi använde de befintliga template-funktionerna.

Resultatet kan du se här: http://elektronikkbransjen.no/Medlem/Medlemsoversikt

All utdata från sql-satserna ovan är förkortade, den vekliga utdatan var mer än 900 rader.
Epost-adresserna i utdatan ovan är modifierade på grund av sekretess.