Space Vatican

când indexați date, lumea este rareori la fel de simplă ca fiecare document existent izolat. Uneori, este mai bine să denormalizezi toate datele în documentele copilului. De exemplu, dacă modelați Cărți, adăugarea unui câmp autor la cărți ar putea fi o alegere sensibilă (chiar dacă în baza de date care este sursa de date autoritară, datele sunt împărțite în tabele separate authors și books). Este simplu și puteți construi cu ușurință interogări pe ambele atribute ale cărții și numele autorului.

acest lucru nu este întotdeauna practic – ar putea exista prea multe date în documentul părinte pentru a le duplica în fiecare document copil. Dacă ați avut tipic blog / comentariu app atunci nu ar vrea să repete întregul conținut al blogului în fiecare comentariu ca acest lucru ar crește foarte mult cantitatea de date indexate mai multe. Cu toate acestea, fără asta nu puteți scrie cu ușurință interogări pentru a găsi comentarii la postări care corespund anumitor criterii (altele decât făcând un pas 2 al procesului de a găsi mai întâi postări potrivite și apoi de a prelua comentarii cu un anumit post_id, care este adesea greoi sau lent (sau ambele)).

o altă opțiune este de a plasa documente copil în interiorul documentului părinte, de exemplu, puteți avea documente ale formularului

123456789101112
{ "name": "A. N Author", "biography": "A leading wordsmith", "books": }

un dezavantaj aici este că adăugarea unui copil necesită reindexarea întregului document. Găsirea autorilor care au scris cărți cu un anumit gen este ușoară, dar găsirea autorilor care au avut o carte de science fiction publicată de penguin este mai dificilă.

dacă indexul nostru conține

atunci cea mai evidentă interogare

îi găsește pe ambii autori – nu puteți exprima că condițiile dvs. de pe published și genre trebuie să se potrivească cu aceeași carte.

ElasticSearch oferă două lucruri care ajută la acest lucru. Primul este conceptul de document/interogare imbricată. Acest lucru vă permite să spuneți că căutați autori în care cel puțin o carte îndeplinește ambele criterii.

mai întâi trebuie să configurați o mapare care spune că câmpul cărți va fi imbricat:

123456789
curl -XPOST localhost:9200/authors/nested_author/_mapping -d '{ "nested_author":{ "properties":{ "books": { "type": "nested" } } }}'

dacă introducem apoi aceleași date ca înainte în acest nou index, atunci această interogare

aici filtrul nested vă permite să rulați o interogare împotriva documentelor imbricate (adică cărțile) și să filtrați autorii după cei care au cel puțin un document imbricat care se potrivește cu interogarea. Opțiunea path ne spune la ce parte a documentului autorilor se aplică această interogare și apoi opțiunea query este o interogare pentru a rula împotriva acestor documente imbricate. Spre deosebire de interogarea anterioară, aceasta necesită găsirea unei cărți individuale care să satisfacă ambele cerințe, astfel încât numai Alaistair Reynolds este returnat

părinte & copil

celălalt concept pe care elasticsearch îl oferă este cel al relației părinte-copil dintre documente. Exemplul anterior poate fi refăcut cu autori ca documente părinte și cărți ca documente copil.

de data aceasta, indexați autorii separat de cărțile lor:

apoi configurați maparea pentru tipul de carte și spuneți că tipul său părinte este bare_author. Trebuie să faceți acest lucru înainte de a crea cărți.

12345
curl -XPOST localhost:9200/authors/book/_mapping -d '{ "book":{ "_parent": {"type": "bare_author"} }}'

când indexăm Cărți, trebuie să dați id-ul părintelui lor (adică furnizăm id-ul unuia dintre autorii creați anterior)

Elasticsearch oferă un filtru has_child care face destul de mult ceea ce spune pe tablă: Selectează documentele părinte cu cel puțin un copil care îndeplinește o anumită interogare. Această interogare găsește apoi doar Alastair Reynolds:

Solr 4.0 va avea aparent capacitatea de a face se alătură, deși, din câte pot spune, acest lucru vine cu unele restricții, în special nu se alătură dacă sunteți operat într-un mediu distribuit. Limitându-se la relațiile de tip părinte/copil elasticsearch face viața mai ușoară pentru sine: un copil este întotdeauna indexat în același ciob ca părintele său, deci has_child nu trebuie să facă operații incomode de ciob încrucișat.

liste de construcție

de asemenea, puteți utiliza acest lucru pentru a modela liste specifice utilizatorului de articole globale partajate – de exemplu, dacă doriți articole pe care un utilizator le-a evaluat. În acest caz, documentele copilului dvs. ar reprezenta faptul că un anumit utilizator a evaluat un anumit post – nu sunt altceva decât un user_id, post_id și un rating: un tabel de înscriere în jargonul bazei de date relaționale.

utilizarea unei relații părinte/copil și has_child vă permite să găsiți cu ușurință toate postările preferate de un utilizator, permițând în același timp utilizatorilor să caute prin favoritele lor pe baza conținutului postării, a datei sau a oricăror alte atribute ale postării sau a oricăror proprietăți ale elementului copil. Adăugarea unui articol în lista de articole evaluate este ieftină – necesită doar indexarea unui articol foarte mic rating.

cu aceste documente

această interogare

găsește doar „bolivia evaluat 4”, deoarece aceasta este singura postare care menționează bolivia care a fost evaluat peste 3 de către utilizatorul care ne interesează. Interogarea de nivel superior pe titlu se aplică postărilor, unde interogarea din filtrul has_child descrie condițiile pe care copiii trebuie să le corespundă (în acest caz trebuie să aparțină unui anumit utilizator și să aibă cel puțin o anumită evaluare).

ordonarea

ceea ce has_child nu vă permite să faceți este să comandați pe baza atributelor copiilor sau să returnați atributele copilului. Dacă doriți să comandați postările unui utilizator evaluate în funcție de momentul în care au fost evaluate sau prin scăderea ratingului, puteți căuta direct în funcție de postări/evaluări, dar este posibil să doriți să aplicați și unele criterii de căutare postărilor. De exemplu, s-ar putea să doriți să găsiți doar postări evaluate pe un anumit subiect (ordonând în continuare după evaluarea pe care a dat-o Utilizatorul). Cu has_child, nu ai noroc. Nici documentele imbricate nu ajută.

începând cu 0.19.10 puteți utiliza filtrul has_parent. Acest lucru funcționează aproape exact la fel ca are copil, dar vă permite să specificați o interogare împotriva elementele părinte în schimb. Această interogare returnează evaluările după utilizatorul 1234, pe postările al căror titlu se potrivește cu „bolivia”, în ordinea scorului descrescător

aceasta returnează obiectele de evaluare – va trebui apoi să preluați postările corespunzătoare cu o interogare separată.

Faking it

dacă sunteți blocat pe o versiune mai veche a elasticsearch, puteți obține cea mai mare parte a drumului acolo cu top_children. După cum spune documentația top_children interoghează mai întâi documentele copilului și apoi le agregă în documente părinte. În exemplul nostru, aceasta înseamnă că elasticsearch va găsi mai întâi documentele de evaluare care se potrivesc interogării noastre. Apoi se va potrivi fiecare evaluare la postul său părinte, agregarea post duplicat în cazul în care acestea există.

partea fiddly cu copiii de top este că elasticsearch nu știe din timp câte documente va pierde atunci când se va întâmpla agregarea. În acest caz particular, este ușor, deoarece două evaluări distincte ale aceluiași utilizator corespund întotdeauna la două postări distincte, deci nu trebuie să ne deranjăm cu setările factor și incremental_factor, deoarece faza de agregare nu face niciodată nimic. În mod similar, nici modul scor nu contează. Dacă trebuie să furnizați un număr precis al numărului total de rezultate, trebuie doar să setați factor suficient de mare încât prima sweep elasticsearch să facă documentele copilului să le găsească pe toate. Dacă știți că utilizatorul are 500 de articole evaluate pe lista lor și solicitați primele 10 articole, atunci un factor de 50 ar trebui să facă trucul. Factorul trebuie să fie doar o limită superioară – nu trebuie să știți exact câte elemente are utilizatorul pe lista lor (ceea ce ar putea fi dificil de rezolvat fără o interogare de căutare elastică separată dacă utilizatorul caută un anumit subset al evaluărilor sale).

ceea ce obțineți după toate acestea este o listă de documente părinte (postări) sortate după scorul de interogare al documentelor pentru copii (evaluări). Pentru a atinge obiectivul inițial de sortare a postărilor pe baza atributelor documentelor pentru copii, trebuie doar să ne asigurăm că acest scor de interogare are valoarea corectă. De exemplu, aveți top_children query wrap o interogare custom_score, astfel încât să aveți control asupra scorului pentru fiecare copil.

cu aceleași documente în index, Această interogare returnează postările pe care utilizatorul 1234 le-a evaluat, ordonate după evaluarea lor:

rulăm o interogare top_children, deci primul lucru pe care trebuie să-l facem este să spunem care este tipul de copii pe care îi analizăm (rating). Apoi oferim interogarea care găsește acei copii. Aceasta este o interogare custom_score, înfășurând o interogare filtered. Interogarea filtered ne asigură că găsim doar evaluări date de utilizatorul care ne interesează, iar apoi elementul script face ca scorul documentului de evaluare să fie evaluat în sine, astfel încât să ne ordonăm postările după evaluare. Funkiness cu backslashes este doar pentru că am încercat să includă un singur citat literal într – un șir de caractere prietenos coajă delimitat de citate unice-JSON reale pe care le trimitem are doar "script": "doc.value".

Ruby fun

din păcate, biblioteca de anvelope nu acceptă cu adevărat nimic din aceste lucruri distractive în acest moment – există un pic de moratoriu asupra acestui tip de caracteristică adăugată, deoarece în acest moment fiecare tip de interogare și opțiune sfârșește prin a fi metode separate împrăștiate pe toată anvelopa, pe care responsabilul nu-i place. Puteți Un fel de hack-l în, deși.

anvelopa nu vă permite să setați ID-ul părinte al unui document atunci când indexați. Acest lucru este simplu de adăugat și este reținut doar de moratoriul menționat anterior. Furca mea adaugă această abilitate. Cu asta sfârșești cu

următorul pic de nefericire este că crearea indexului auto al lui tire presupune un tip pe index, dar pentru ca o relație părinte/copil să existe, ambele tipuri trebuie să fie în același index. Am ajuns să fac așa ceva pentru a-mi crea indexurile.

ceea ce nu este la fel de frumos, dar face treaba.

în cele din urmă aveți nevoie pentru a face de fapt interogare. În absența top_children fiind de fapt parte din API-ul tire puteți fudge-l ca atât de

acest pic de neplăcere construiește interogarea ca un hash și apoi împinge-l în anvelope în timp ce se uită în altă parte. Evident, îl puteți structura în așa fel încât să fie ușor să adăugați alte condiții (fie la postare, fie la evaluare) la căutare. De asemenea, puteți construi json manual și de a folosi Post.search :payload => my_json(există un bug cu opțiunea de sarcină utilă care se ciocnește cu extensia Logger tire-contrib)

Lasă un răspuns

Adresa ta de email nu va fi publicată.