Úvodní stránka › Fórum podpory WordPressu › Pluginy (funkčnost webu) › MySql UPDATE meta_value
Štítky: get_posts, import, MySQL, update_post_meta(), WooCommerce, WP All Import
Zvolené téma obsahuje celkem 13 odpovědí. Do diskuze (2 účastníci) se naposledy zapojil uživatel HiLow a poslední změna je stará 6 let, 10 měsíců.
-
AutorPříspěvky
-
6. června 2017 (11:29) #32805
Dobrý den,
potřebuji aktualizovat ceny ve WooCommerce z CSV souboru.Problém je, že produktů je 25k+ a WP All Import aktualizuje ceny déle než 12 hodin.Proto si píšu vlastní script Import/Export a mám problém s UPDATE.
Script na export jede cca 6s a CSV je vyexportovaný
$host = "127.0.0.1"; $uname = "***"; $pass = "***"; $database = "***"; $conn = new mysqli($host, $uname, $pass, $database)or die("No Connection"); echo mysqli_error($conn); //MYSQL TO CSV if (isset($_REQUEST['btn_export'])) { $data_op = ""; $sql = $conn->query(" SELECT pm1.meta_value AS sku, pm2.meta_value AS price FROM ps_posts p LEFT JOIN ps_postmeta pm1 ON (pm1.post_id = p.ID AND pm1.meta_key = '_sku') LEFT JOIN ps_postmeta pm2 ON (pm2.post_id = p.ID AND pm2.meta_key = '_price') WHERE post_type = 'product' "); while ($row1 = $sql->fetch_field()) { $data_op .= '"' . $row1->name . '",'; } $data_op .="\n"; while ($row = $sql->fetch_assoc()) { foreach ($row as $key => $value) { $data_op .='"' . $value . '",'; } $data_op .="\n"; } $filename = "skuceny.csv"; //Change File type CSV/TXT etc header('Content-type: application/csv'); //Change File type CSV/TXT etc header('Content-Disposition: attachment; filename=' . $filename); header('Pragma: no-cache'); header('Expires: 0'); echo $data_op; exit; }
Problém je s UPDATE – zatím jediný funkční dotaz, který jsem sesmolil je strašně pomalý – cca 1s na záznam:
$sql = "UPDATE ps_postmeta a JOIN ps_postmeta b ON a.post_id = b.post_id AND b.meta_key = '_sku' AND b.meta_value LIKE '{$data[0]}' SET a.meta_value = IFNULL(( CASE WHEN a.meta_key = '_price' THEN '{$data[1]}' WHEN a.meta_key = '_regular_price' THEN '{$data[1]}' END),a.meta_value); ";
Potřebuji poradit jak dotaz upravit. Ceny se musí párovat podle SKU, post_id nemám a nemůžu mít.
Ještě mě napadlo použít nějakou tmp tabulku, kde bych zjistil post_id ke _sku a potom to napároval podle post_id, ale tady vůbec nevím jak.
Předem díky za jakoukoliv radu.
6. června 2017 (14:42) #32809Není lepší mít to tlačítko na import někde ve WordPressu a používat jeho funkce než psát vlastní dotazy?
Nejdříve get_posts() s
meta_query
pro_sku
, čímž získáte ID příspěvku a následně už můžete použít pouze update_post_meta()?Nemáte WP All Import jen nějak špatně nastavený? Možná by pomohlo nějak navýšit rychlost zpracování?
Pokud máte 25 tisíc produktů, tak potom máte klidně více než milion postmeta záznamů a když se v tomto objemu dat hledá, tak není 1 sekunda zase tak špatný výsledek. Obecně je s postmeta daty problém a kvůli tomu jsou v nové WooCommerce 3.0.x i nové možnosti, které postupně povedou s dalšími verzemi k tomu, že se data přesunou do nějaké jiné tabulky (a struktury).
Mimochodem v nové verzi WooCommerce 3.1 (měla by vyjít koncem června, ale už můžete klidně testovat) bude možné produkty importovat přímo z CSV.
6. června 2017 (15:18) #32815Právě se chci úplně vyhnout zpracování na straně WP, proto píšu vlastní script. Ten na export je neporovnatelně rychlejší, než kdybych to exportoval přes WP All Export. Vlastně vše zpracuje jen MySQL a PHP jen zapisuje do CSV.
Podobného výsledku bych chtěl dosáhnout i u importu (řádově sekundy). Problém je, že meta_value se nedá indexovat a dotaz vždy prohledá celou tabulku, kde je teď okolo 1M záznamů a má už kolem 280MB. Proto je dotaz pomalý.
Při zkoumání řešení mě napadlo vytvořit další tabulku, do které by se zapsalo jen post_id a _sku.
Zjednodušeně by byla logika dotazu:
První Query: SELECT z wp_postmeta post_id, _sku CREATE novou tabulku a do ní INSERT hodnoty.
Druhý Query: by byl kombinací zjištění post_id podle _sku
Třetí Query by byl již jen UPDATE podle post_id (WHERE post_id = $x) – protože je post_id indexované musí podle mě UPDATE již běžet mnohem rychleji.
Bohužel nějak nevládnu syntaxí MySQL, tak už dva dny studuji, něco mi běží, něco ne, něco je extrémně pomalé atd.
Myslí, že nastíněné řešení by bylo nejlepší, nicméně ho ještě neumím napsat.
Kdyby byl někdo se zkušenostmi, myslím že dotazy má napsané za pár minut.
Předem díky za odpovědi !
6. června 2017 (15:19) #32816Ještě jsem zapomněl, že vše běží na vlastním VPS a zdroje si můžu upravovat (s výkonem problém určitě není), stejně pomalu to běží i na testovacím serveru WP All Import, kde mi kolikrát server vrátí hlášku IMPORT TERMINATED.
6. června 2017 (16:05) #32817Zkouším WC 3.1 a ten nový CSV Import/Export. Pokud je to pro malý eshop do 1000 produktů, tak by to asi i mohlo fungovat. Bohužel pro větší eshopy je to nepoužitelné. Nelze nastavit co vše má aktualizovat a proto spouští u každého produktu dotazy na všechny taxonomie, všechny post_meta, projíždí tabulky wp_terms, wp_term_taxonomy, wp_term_relationships, wp_post_met atd., takže asi ani nepočkám jestli to dojde někdy pozítří dokonce.
Je sice pěkné, že vyjeli s CRUDEm, který WC posouvá zase kousek dál, ale kdyby radši místo toho opustili post_meta (podle mého na toto není vůbec vhodná ani navržená) a navrhli vlastní db strukturu udělali by daleko lépe a zrychlení by mohlo být více než znatelné.
Teď se ještě dívám na class WC_Data_Store (WC >3.0) respektive WC_Data, to vypadá dobře, nicméně zase jen na čtení (udržuje se v cache $cache_group), v zápisu to ale výkon asi nepřinese.Čili pro mě nezbývá nic jiného než zprovoznit ten script.
PS: ceny by mě ani moc netlačili, ty se mění třeba jednou denně, ale _stock by se měl synchronizovat cca 10x denně.
6. června 2017 (16:52) #32818Ano, WooCommerce 3.0 je pouze začátek, jakmile se to trochu zažije, tak se myslím změní i databázová struktura.
Ale zpátky k problému, co se na to zkusit podívat trochu jinak a opustit způsob hrubé síly? Sice máte 25 tisíc produktů, ale denně se cena změní u kolika z nich? A skladové zásoby se také nebudou měnit 10x denně u všech produktů? Nešlo by aktualizovat pouze to, co je potřeba? nevím, odkud jsou data z CSV, ale nešlo by se nějak přímo napojit na systém, odkud pocházejí?
Další možností, která mě napadá, je CSV pravidelně importovat do samostatné databázové tabulky a cenu i skladové zásoby podstrčit WooCommerce pomocí hooků. Pak by mohlo být v administraci zadané cokoli, ale eshop by si načítal hodnoty z vlastní tabulky (pomocí jednoduchého selectu).
6. června 2017 (17:07) #32820CSV je od dodavatele v celkem nepoužitelné struktuře. Takže si ho pomocí skriptu nejdřív stáhnu z FTP, přeparsuji a uložím.
Váš nápad je ale vcelku geniální. Víceméně můžu nechat na disku poslední kopii CSV, stáhnout nový a porovnat rozdíly a ty pak uložit do CSV na import. To v případě cen.
V případě skladu je to ovšem trochu jiné. Jedná se o rychloobrátkové zboží, kde se synchronizuje sklad od dodavatele a ne sklad prodejce. Určitě tím ušetřím “hrubou sílu”, ale nevím na kolik. Taky si předem neumím představit návštěvnost a prodeje a měl bych rád nějakou “rezervu” ve výkonu.
Ta Vaše další možnost vypadá možná úplně nejlépe, ale moc si to neumím představit. Pravděpodobně by těch hooků muselo být moře, aby se cena projevila všude (product, order atd.) Nebo stačí jeden hook např.:
add_filter('woocommerce_get_price', 'return_custom_price', 10, 2);
?
A do funkcereturn_custom_price()
narvat SQL dotaz ?6. června 2017 (19:26) #32822Tak filter
woocommerce_get_price
je magický. Změněná cena se projeví všude (product, order, email) a můžu si s ní dělat co chci, třeba tahat ceny z jiné DB.Takže založím novou tabulku, do ní budu importovat ceny z CSV a vše spouštět cronem.
Teď ještě podobně vyzrát na _stock.
6. června 2017 (21:34) #32824@hilow: Díky :-) Nešlo by skladové zásoby ještě optimalizovat, že byste neaktualizoval konkrétní počty, ale prostě jen doplňoval Skladem/Není skladem? A provedl to automaticky už při parsování CSV? Příklad: Pokud je počet kusů skladem 23, tak nikoho moc nezajímá, že počet kusů poklesl z 25 na 23 a je to prostě “Skladem”. Pokud je počet kusů menší než 10, tak už budeme porovnávat aktuální čísla a uvádět je na webu. Tím by se mohl ještě více snížit počet aktualizovaných produktů, kolik se jich z 25 tisíc změní na Skladem/Není skladem? Podle mě jich moc nebude, i když se třeba započtou produkty s nízkými počty, které se aktualizovat budou. Potom budete mít pár stovek změněných produktů a s tím si poradí i WP All Import automaticky za pár minut.
Ad druhý způsob: Ano, cenu i skladové zásoby by mělo stačit filtrovat pouze na jednom místě, WooCommerce pak s těmito základními funkcemi počítá dále. Takže změněná cena se dostane do košíku a případně se pak transformuje do objednávky, ale vychází se pouze z jednoho místa. Vlastně pomocí filtru podstrčíte WooCommerce zcela jiná data :-)
Ale úplně nejlepší způsob by byl v přímém napojení na dodavatele :-) Sice exportuje nějaké CSV na FTP, ale třeba to exportuje z nějakého systému, který má nějaké API a šlo by to vyřešit snadno a rychle…
6. června 2017 (23:26) #32830Tak SUPER!
Ceny 25k+ produktů jsou importovány za cca 2s – to je nesrovnatelný rozdíl!
Postup:
Z FTP stáhnu a naparsuji CSV, to předám další části skriptu, který CSV naimportuje do MySQL do nové tabulky, kterou před každým importem vyprázdní.Zobrazení cen na webu pak řeší následující funkce (ve function.php v child theme)
add_filter('woocommerce_product_get_price', 'nt_product_custom_price', 10, 2); function nt_product_custom_price($price, $product) { $csv_price = $product->get_regular_price(); $wcsku = $product->get_sku(); global $wpdb; $querystr = "SELECT price FROM nt_ceny WHERE sku = $wcsku"; $ntprice = $wpdb->get_results($querystr, OBJECT); foreach ($ntprice as $newprice){ $csv_price = $newprice->price; } return $csv_price; }
Zde se ještě změnil hook od WC > 3.1 z
woocommerce_get_price
nawoocommerce_product_get_price
.Co se týče skladových zásob je to požadavek od klienta, který požaduje zobrazení ks. Také zákazníci se rozhodují podle toho, kolik ks je skladem potřebují totiž ve většině případů 4 ks, minimálně však 2 ks.
Skladem/není skladem nic neřeší, také je to custom_field. Jedině porovnávat rozdíly a z nich aktualizovat.
Neznáte nějaký hook na _stock ?
Zatím jsem jenom našel funkci$product->get_stock_quantity
S dodavatelem bohužel není technická dohoda možná, dokonce jsem ho nepřesvědčil aby data dal na https místo na FTP, takže jsem musel do WP All Import psát spoustu funkcí, aby si stáhl soubor z FTP, obrázky z FTP atd., protože WPALLI neumí nativně pracovat se soubory z FTP. Jejich datová struktura je taky neuvěřitelná, nehledě na duplicitní identifikátory apod. Někdy mi to připadá, že to snad neleze ze systému, ale že to někdo datluje ručně.
Příspěvek se odeslal, ale nikde ho nevidím :-( tak znovu.
6. června 2017 (23:49) #328317. června 2017 (10:38) #32833Díky za detailní report! myslím, že může být celé téma zajímavé i pro mnoho dalších uživatelů :-)
Skladem/není skladem toho řeší hodně, pokud máte u nějakého zboží 25 ks a změní se to s novým exportem na 23 ks, tak to budete muset aktualizovat, ale pokud by stačila hodnota “Skladem”, tak ta zůstane stále stejná a nic se aktualizovat nemusí. Pokud je tam ale požadavek na zobrazení přesného počtu kusů, tak s tím asi nic neuděláme :-) Jen bych se těm kusům raději vyhnul, protože i když to modifikujete prostřednictvím filtru, tak se to bude v administraci a u objednávek odečítat a bude v tom trochu bordel (i když to pak ale vždycky stejně aktualizujete). Jak to bude vlastně fungovat, když na eshopu dojde k objednávce? Z 23 ks počet klesne na 22 a to se zároveň změní i u dodavatele na 22 ks? Nebo tam pak za pár hodin zase naimportujete původních 23 ks? Potom to nedává moc smysl a bohatě by stačila informace “Skladem”?
Mizející příspěvky občas zlikviduje Akismet, stačí napsat, že se ztratil a vytáhnu ho z koše :-)
7. června 2017 (13:32) #32841Detailní report dávám jak kvůli někomu, komu by to mohlo pomoct, tak i kvůli tomu, kdybych to někdy potřeboval :-)
Kusy se budou aktualizovat asi jednou za 10 minut (ne jak bylo původně 10x denně) Script běží necelou vteřinu, takže v tom problém nebude.
Po objednávce ve WC se odešle objednávka k dodavateli a tím pádem vygeneruje nové CSV se správným počtem kusů.
Takže jsem vlastně obešel WooCommerce a sklad řeší externí řešení.Nicméně ty filtry se mi líbí čím dál víc, když si s tím pohraji, tak vlastně můžu WC použít jen jako framework s bonusem tisíce různých pluginů, ale data si můžu zpracovávat úplně někde jinde s neporovnatelnou rychlostí.
WC je moc dobrý eshop kvůli jeho dokumentaci, rozšiřitelnosti apod., ale rychlost je tragická. Samozřejmě s každou novou verzí je lepší a rychlejší, nicméně na eshop s desetitisíci produkty a nějakou automatizací procesů je v základu nepoužitelný. Nese si totiž bohužel “dědictví” z WP v podobě návrhu tabulek. Vím že je to pro vývoj lehčí (používají se nativní f-ce WP), ale je to zase omezené funkčností WP.
Asi začnu podrobněji zkoumat API, protože kdyby se mi podařilo přes nějaké filtry přemluvit WC aby nativně používali jinou tabulku z DB s mou vlastní strukturou, byl by to velice mocný nástroj. Tomu ale moc nevěřím, ale bylo by to super.
PS: Kdyby České služby taky nemuseli data tahat z postmeta, ale bylo by to v nějaké indexované tabulce, feed by mohl být vygenerovaný při 30k+ produktech během pár vteřin.
Díky moc za pomoc a postrčení správným směrem!
8. června 2017 (18:57) #32861Další věcí, kterou jsem tímto zjistil je že NIKDY nezakládejte více vlastností než je bezpodmínečně nutné.
S každou další vlastností tabulka postmeta roste geometrickou řadou a veškeré dotazy probíhají pomaleji. Takže pro jednoduchý produkt zvolte jen vlastnosti podle kterých chcete filtrovat, ostatní si vložte třeba ve formě tabulky do popisu produktu.Při hodně produktech a hodně vlastnostech může mít tabulka třeba 1M záznamů a velikost 300MB, po přesunutí do popisu se můžete dostat na desetinu.
-
AutorPříspěvky
Pokud chcete odpovědět na toto téma, musíte se nejdříve přihlásit.