Jak vyřešit ukázkový příklad v ORM

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
norbe
Backer | 405
+
0
-

Momentálně se porozhlížím po nějakém ORM a zajímalo by mně, jestli a případně jak jde v ORM které používáte/vytváříte vyřešit následující příklad:

Jsem zvyklý si často používané údaje vypočítat už v db, abych pak nemusel provádět dotaz pro každý řádek zvlášť. Jak ale pomocí ORM získám např. údaj o tom, kolik je produktů v dané kategorii(včetně podkategorií – předpokládám hiearchickou strukturu s lft a rgt)?

Pomocí SQL to řeším nějak takto:

SELECT ['.self::CATEG_TABLE.'].*,
IFNULL([stat].[prods_in_cat], 0) AS prods_in_cat,
FROM ['.self::CATEG_TABLE.'] AS c
LEFT JOIN ( -- get count of products in category
	SELECT c.id, SUM( prod.count ) AS prods_in_cat
	FROM ['.self::CATEG_TABLE.'] AS c -- current category
	JOIN ( -- count all products in child categories
		SELECT prod.category_id, COUNT( prod.id ) AS count
		FROM ['.Product::PROD_TABLE.'] AS prod
		GROUP BY prod.category_id
	) AS prod ON prod.category_id IN ( -- get all child categories
		SELECT id
		FROM ['.self::CATEG_TABLE.'] AS orig
		WHERE (orig.lft >= c.lft AND orig.rgt <= c.rgt)
	)
	GROUP BY id
) AS stat

Co jsem zatím zkouknul nějaké jednoduché příklady různých ORM, tak se to řeší getterem, který se volá pro každý řádek zvlášť. Existuje tedy nějaké ORM, které toto nějakým způsobem řeší, nebo zastáváte názor, že těch pár (desítek) dotazů se ztratí? :-)

Patrik Votoček
Člen | 2221
+
0
-

Tohle by teoreticko mohlo jít něják elegantně řešit v Doctrine 2.0… Popátrám a doplním odkaz (pokud to nestihne někdo rychleji)…

srigi
Nette Blogger | 558
+
0
-

Doctrine ma pomerne silny „dotazovaci“ jazyk DQL vid. dokumentacia. Ma aj vstavanu podporu Nested set (traverz. okolo stromu) a to aj s podporou pre fetch tree with reations

Patrik Votoček
Člen | 2221
+
0
-

OT: srigi nevíš kdy by měla být 2.0 finalizována (stable)?

srigi
Nette Blogger | 558
+
0
-

vrtak-cz napsal(a):

OT: srigi nevíš kdy by měla být 2.0 finalizována (stable)?

Skus checknut tento slideshare.

mkoubik
Člen | 728
+
0
-

Nebylo by lepší si na to udělat view a pak to z ORM tahat standardně?

norbe
Backer | 405
+
0
-

No to už mně taky napadlo. Ale jak bych pak provedl např. insert u ORM, které právě vznikají pro Dibi (Ormion, ActiveRecords – obě ORM se mi totiž velmi líbí :))? Umožňují nějak definovat, aby se data brala z pohledu a ukládala do tabulky?

Honza Marek
Člen | 1664
+
0
-

norbe napsal(a):

No to už mně taky napadlo. Ale jak bych pak provedl např. insert u ORM, které právě vznikají pro Dibi (Ormion, ActiveRecords – obě ORM se mi totiž velmi líbí :))? Umožňují nějak definovat, aby se data brala z pohledu a ukládala do tabulky?

U Ormionu si můžeš k Recordu nastavit vlastní mapper. Tzn. asi by sis podědil normální OrmionMapper a přepsal třeba metodu pro ukládání záznamu.

pekelnik
Člen | 462
+
0
-

Osobne neznam ORM, ve kterem by sel „napsat“ tento dotaz. DQL z Doctrine je pomerne silne, avsak troufnu si tvrdit (nezkousel jsem), ze ani tam tohle nedate.

phx
Člen | 651
+
0
-

Nezkousel jste nekdo udelat test vykonosti? Jak si stoji mezi sebou:

  • 1 dotaz
  • hromada dotazu (co radek to novy dotaz)
  • ci Jakubovo NotORM

Mohlo by to byt zajimave srovnani zda pro DB je lepsi 1 sileny dotaz ci „20“ jednoduchych.

vrana
Člen | 131
+
0
-

Já bych to v NotORM napsal takhle:

<?php
$update = array();
$categories = array();
foreach ($shop->category()->order("lft") as $id => $category) {
	list($category["count"]) = $category->product()->group("COUNT(*)");
	$categories[$id] = $category;

	// zvýšení počtu rodičů
	foreach ($update as $key => $val) {
		if ($val["rgt"] > $category["rgt"]) {
			$val["count"] += $category["count"];
		} else {
			unset($update[$key]);
		}
	}
	$update[] = $category;
}
?>

Položí se celkem dva dotazy, rychlost bude výborná (lepší než u původního řešení). Přehlednost je také dramaticky lepší.

phx
Člen | 651
+
0
-

Otazka zni zda vypocet MySQL nebude rychlejsi nez 2× MySQL + PHP. Predci jen v PHP jede cyklus N*(N-1).

Jsem k tomu trochu skepticky, protoze par poslednich let slychavam co muze udelat DB at DB udela.

JakubJarabica
Gold Partner | 184
+
0
-

@phx:
Tiez zastavam podobny nazor, ale napriklad toto je velmi zaujimave: Digg NoSQL

vrana
Člen | 131
+
0
-

phx napsal(a):

Otazka zni zda vypocet MySQL nebude rychlejsi nez 2× MySQL + PHP. Predci jen v PHP jede cyklus N*(N-1).

Když se podívám na ten původní dotaz, tak moc nevidím šanci, že by se na to daly efektivně využít indexy (zkuste si nad tím dotazem EXPLAIN).

Cyklus neběží v čase O(N*N), ale O(N*M), kde M je hloubka zanoření. To je dramaticky lepší, protože hloubka zanoření je obvykle nízká (nebo někdy dokonce programově omezena). O(N*N) by to bylo jen u stromů s jediným listem (neboli holých větví).