Pracuję nad projektem, w którym tworzę niestandardowy typ postu i niestandardowe dane wprowadzane za pomocą pól meta powiązanych z moim niestandardowym typem postu. Z jakiegokolwiek powodu postanowiłem zakodować meta-boxy w taki sposób, aby dane wejściowe w każdym metaboksie były częścią tablicy. Na przykład przechowuję długość i szerokość geograficzną:
<p>
<label for="latitude">Latitude:</label><br />
<input type="text" id="latitude" name="coordinates[latitude]" class="full-width" value="" />
</p>
<p>
<label for="longitude">Longitude:</label><br />
<input type="text" id="longitude" name="coordinates[longitude]" class="full-width" value="" />
</p>
Z jakiegokolwiek powodu podobał mi się pomysł posiadania osobnego wpisu postmeta dla każdego metaboxa. Na save_post
haku zapisuję dane w następujący sposób:
update_post_meta($post_id, '_coordinates', $_POST['coordinates']);
Zrobiłem to, ponieważ mam trzy metaboksy i lubię mieć 3 wartości postmeta dla każdego postu; zdałem sobie jednak sprawę z tego potencjalnego problemu. Mogę chcieć użyć WP_Query do wyciągania tylko niektórych postów na podstawie tych meta wartości. Na przykład mogę chcieć uzyskać wszystkie posty, które mają wartości szerokości geograficznej powyżej 50. Gdybym miał te dane w bazie danych osobno, być może używając klucza latitude
, zrobiłbym coś takiego:
$args = array(
'post_type' => 'my-post-type',
'meta_query' => array(
array(
'key' => 'latitude',
'value' => '50',
'compare' => '>'
)
)
);
$query = new WP_Query( $args );
Ponieważ mam szerokość geograficzną jako część _coordinates
postmeta, to nie zadziałałoby.
Moje pytanie brzmi: czy istnieje sposób wykorzystania meta_query
zapytania do szeregowanej tablicy, jak w tym scenariuszu?
źródło
Wpadłem również na tę sytuację. Oto co zrobiłem:
Mam nadzieję, że to pomoże
źródło
$value
to również identyfikatora. W takim przypadku sugeruję utworzenie funkcji, aby dodać znak do każdego elementu tablicy przed zapisaniem danych oraz innej funkcji, aby usunąć znak przed użyciem danych. W tym przypadku szeregowanyi:2
indeks nie będzie mylony zi:D2
„prawdziwymi” danymi. Parametr meta kwerendy powinien stać się,'value' => sprintf(':"D%s";', $value),
a Ty zachowasz poprawną funkcjonalność tej wspaniałej odpowiedzi!LIKE
to świetny i szybki sposób na obniżenie poziomu serwera (nie wspominając o fałszywych alarmach), dlatego lepiej mieć bardzo dobre buforowanie.Naprawdę stracisz możliwość kwerendowania swoich danych w jakikolwiek efektywny sposób podczas szeregowania wpisów do bazy danych WP.
Ogólna oszczędność wydajności i zysk, który według ciebie osiągasz dzięki serializacji, nie będzie zauważalny w znacznym stopniu. Możesz uzyskać nieco mniejszy rozmiar bazy danych, ale koszt transakcji SQL będzie wysoki, jeśli kiedykolwiek zapytasz te pola i spróbujesz je porównać w jakikolwiek użyteczny, znaczący sposób.
Zamiast tego zapisz serializację dla danych, których nie zamierzasz odpytywać w tym charakterze, ale zamiast tego uzyskasz dostęp tylko w sposób pasywny przez bezpośrednie wywołanie WP API
get_post_meta()
- z tej funkcji możesz rozpakować szeregowany wpis, aby uzyskać dostęp do jego właściwości tablicy.W rzeczywistości przypisano wartość true jak w;
$meta = get_post_meta( $post->ID, 'key', true );
Zwróci dane w postaci tablicy, dostępnej w celu iteracji, jak zwykle.
Możesz skupić się na innych optymalizacjach baz danych / witryn, takich jak buforowanie, minimalizacja CSS i JS oraz używanie takich usług jak CDN, jeśli potrzebujesz. Żeby wymienić tylko kilka ... Kodeks WordPress to dobry punkt wyjścia, by dowiedzieć się więcej na ten temat: TUTAJ
źródło
Właśnie poradziłem sobie z serializowanymi polami i mogę je zapytać. Nie używając meta_query, ale używając zapytania SQL.
Zapytanie najpierw wyszukuje post z pasującym typem post_, więc liczba rekordów wp_postmeta będzie mniejsza do filtrowania. Następnie dodałem instrukcję where, aby dodatkowo zmniejszyć liczbę wierszy poprzez filtrowanie
meta_key
Identyfikatory ładnie kończą się w tablicy, zgodnie z potrzebą get_posts.
PS. MySQL w wersji 5.6 lub nowszej jest potrzebny do dobrej wydajności podkwerend
źródło
Ten przykład naprawdę mi pomógł. Jest specjalnie dla wtyczki S2Members (która serializuje metadane użytkownika). Ale pozwala na zapytanie o część szeregowej tablicy w obrębie meta_key.
Działa przy użyciu funkcji REGEXP MySQL.
Oto źródło
Oto kod, który odpytuje wszystkich użytkowników mieszkających w USA. Z łatwością zmodyfikowałem go, aby przeszukiwał jedno z moich niestandardowych pól rejestracji i działał w mgnieniu oka.
źródło
Myślę, że istnieją 2 rozwiązania, które mogą spróbować rozwiązać problem przechowywania wyników zarówno jako Ciąg, jak i Liczby całkowite. Jednak ważne jest, aby powiedzieć, jak zauważyli inni, że nie można zagwarantować integralności wyników przechowywanych jako liczba całkowita, ponieważ ponieważ te wartości są przechowywane jako szeregowane tablice, indeks i wartości są przechowywane dokładnie z tym samym wzorcem. Przykład:
jest przechowywany jako szeregowa tablica, taka jak ta
Zwróć uwagę na
i:0
pierwszą pozycję tablicy ii:37
pierwszą wartość. Wzór jest taki sam. Ale przejdźmy do rozwiązań1) Rozwiązanie REGEXP
To rozwiązanie działa dla mnie niezależnie od tego, czy meta wartość jest zapisywana jako ciąg znaków lub liczba / identyfikator. Jednak używa
REGEXP
, co nie jest tak szybkie jak używanieLIKE
2) PODOBNE rozwiązanie
Nie jestem pewien różnicy w wydajności, ale jest to rozwiązanie, które używa,
LIKE
a także działa zarówno na liczbę, jak i na ciągi znakówźródło
REGEXP
w niektórych sytuacjach jest miły, ale jeśli możesz użyćLIKE
, myślę, że jest to preferowana metoda. Stary link, ale nadal bardzo przydatny, moim zdaniem: Thingsilearn.wordpress.com/2008/02/28/… :-)LIKE
jest szybszy. Ale to rozwiązanie działa zarówno na ciągi, jak i liczbyLIKE
ale działa zarówno na liczby, jak i na ciągi znaków. Nie jestem pewien co do wydajności, ponieważ musi ona porównać wyniki przy użyciuOR
Po przeczytaniu kilku wskazówek dotyczących uruchamiania
WP_Query
filtrowania według szeregowanych tablic, oto, jak w końcu to zrobiłem: tworząc tablicę wartości oddzielonych przecinkami za pomocą implode w połączeniu z$wpdb
niestandardowym zapytaniem SQL używanymFIND_IN_SET
do przeszukiwania listy oddzielonych przecinkami żądanej wartości.(jest to podobne do odpowiedzi Tomasa, ale jest nieco mniej wydajne w przypadku zapytania SQL)
1. W functions.php:
W pliku functions.php (lub gdziekolwiek ustawiasz meta box) w
yourname_save_post()
użyciu funkcjiaby utworzyć tablicę zawierającą wartości oddzielone przecinkami.
Będziesz także chciał zmienić zmienną wyjściową w
yourname_post_meta()
funkcji budowy meta-skrzynki administratora na2. W szablonie pliku PHP:
Test: jeśli uruchomisz tablicę
get_post_meta( $id );
, powinieneś zobaczyć jącheckboxArray
jako tablicę zawierającą wartości oddzielone przecinkami zamiast tablicy zserializowanej.Teraz budujemy nasze niestandardowe zapytanie SQL przy użyciu
$wpdb
.Zauważ
FIND_IN_SET
, że tam właśnie dzieje się magia.Teraz ... ponieważ używam
SELECT *
tego, zwraca wszystkie dane postu, a wewnątrzforeach
możesz wydobyć z niego to, czego chcesz (zrób,print_r($posts);
jeśli nie wiesz, co jest zawarte. Nie konfiguruje „pętli” dla ty (wolę to w ten sposób), ale możesz go łatwo zmodyfikować, aby skonfigurować pętlę, jeśli wolisz (spójrz nasetup_postdata($post);
kodeks, prawdopodobnie będziesz musiał zmienić,SELECT *
aby wybrać tylko identyfikatory postów i$wpdb->get_results
odpowiedni$wpdb
typ - - patrz kodeks$wpdb
również w celu uzyskania informacji na ten temat).Cóż, zajęło to trochę wysiłku, ale ponieważ
wp_query
nie obsługuje wykonywania wartości'compare' => 'IN'
zserializowanych lub oddzielonych przecinkami, podkładka ta jest najlepszą opcją!Mam nadzieję, że to komuś pomoże.
źródło
Jeśli użyjesz
like
operatora porównania w meta zapytaniu, powinno dobrze działać, aby zajrzeć do tablicy zserializowanej.prowadzi do:
źródło
Jeśli moje metadane są typu tablic, używam tej metody do zapytania według meta:
źródło
Zainteresowałem się powyższymi odpowiedziami, w których
meta_query
celowałem w kluczlatitude
zamiast_coordinates
. Musiałem przejść i sprawdzić, czy w meta-kwerendach naprawdę można było kierować określony klucz w szeregowanej tablicy. :)Oczywiście tak nie było.
Zauważ, że
_coordinates
zamiast tego jest prawidłowy klucz do celulatitude
.UWAGI:
Takie podejście umożliwia celowanie tylko w dokładne mecze. Tak więc rzeczy takie jak wszystkie szerokości geograficzne większe niż 50 nie są możliwe.
Aby dołączyć dopasowania podłańcuchowe, można użyć
'value' => sprintf(':"%%%s%%";', $value),
. (nie testowałem)źródło
Mam to samo pytanie. Może potrzebujesz parametru „typ”? Sprawdź to powiązane pytanie: Niestandardowe zapytanie o pole - wartość meta to Array
Może spróbuj:
źródło
Wpadłem na coś podobnego podczas korzystania z wtyczki Magic Fields. To może załatwić sprawę
źródło
serialize()
w tym przypadku nie jest wymagane ...