Space Vatican

når du indekserer data, er verden sjelden så enkelt som hvert dokument som eksisterer i isolasjon. Noen ganger er det bedre å denormalisere alle data i barnedokumenter. Hvis du for eksempel modellerte bøker, kan det være et fornuftig valg å legge til et forfatterfelt i bøker(selv om dataene i databasen som er din autoritative datakilde, er delt inn i separate authors og books tabell). Det er enkelt, og du kan enkelt konstruere spørringer på både attributter av boken og forfatterens navn.

det er ikke alltid praktisk – det kan være for mye data i det overordnede dokumentet til å duplisere det i hvert barnedokument. Hvis du hadde din typiske blogg / kommentarapp, ville du ikke gjenta hele innholdet i blogginnlegget i hver kommentar, da dette ville øke mengden indekserte data betydelig. Men uten det kan du ikke enkelt skrive spørringer for å finne kommentarer på innlegg som samsvarer med bestemte kriterier (annet enn ved å gjøre et 2-trinns prosess for først å finne matchende innlegg og deretter hente kommentarer med en viss post_id, som ofte er uhåndterlig eller sakte (eller begge deler)).

Et annet alternativ er å plassere underordnede dokumenter i det overordnede dokumentet, for eksempel kan du ha dokumenter av skjemaet

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

en ulempe her er at å legge til et barn krever reindexing hele dokumentet. Finne forfattere som har skrevet bøker med en bestemt sjanger er lett, men å finne forfattere som har hatt en science fiction bok utgitt av penguin er vanskeligere.

hvis vår indeks inneholder

finner den mest åpenbare spørringen

begge forfatterne – du kan ikke uttrykke at forholdene dine på published og genre må samsvare med samme bok.

ElasticSearch gir to ting som hjelper med dette. Den første er konseptet med et nestet dokument / spørring. Dette lar deg si at du leter etter forfattere der minst en bok tilfredsstiller begge kriteriene dine.

først må du sette opp en tilordning som sier at bøker-feltet skal nestes:

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

hvis vi setter inn de samme dataene som før i denne nye indeksen, kan denne spørringen

her nested – filteret du kan kjøre en spørring mot de nestede dokumentene (dvs.bøkene) og filtrere forfattere av de som har minst ett nestet dokument som samsvarer med spørringen. Alternativet path forteller oss hvilken del av forfatterdokumentet denne spørringen gjelder for, og deretter er alternativet query en spørring som skal kjøres mot disse nestede dokumentene. I motsetning til forrige spørring krever dette at en individuell bok blir funnet som tilfredsstiller begge kravene, slik at Bare Alaistair Reynolds returneres

Foreldre & barn

det andre konseptet elasticsearch gir er at det er et foreldre – og barnforhold mellom dokumenter. Det forrige eksemplet kan omarbeides med forfattere som overordnede dokumenter og bøker som underordnede dokumenter.

denne gangen indekserer forfatterne separat fra bøkene sine:

konfigurer deretter tilordningen for boktypen og si at den overordnede typen er bare_author. Du må gjøre dette før du lager noen bøker.

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

når vi indekserer bøker, må du da gi iden til foreldrene sine (dvs. vi leverer iden til en av de tidligere opprettede forfatterne)

Elasticsearch gir et has_child filter som gjør ganske mye hva som står på tin: den velger foreldre dokumenter med minst ett barn tilfredsstille en bestemt spørring. Denne spørringen finner da Bare Alastair Reynolds:

Solr 4.0 vil tilsynelatende ha muligheten til å gjøre joins, men så vidt jeg kan fortelle dette kommer med noen begrensninger, spesielt ingen joins hvis du drives i et distribuert miljø. Ved å begrense seg til foreldre/barn type relasjoner elasticsearch gjør livet enklere for seg selv: et barn er alltid indeksert i samme shard som sin forelder, så has_child trenger ikke å gjøre vanskelige cross shard operasjoner.

Bygningslister

du kan også bruke Dette til å modellere brukerspesifikke lister over delte globale elementer-f. eks. hvis du vil ha elementer som en bruker har vurdert. I dette tilfellet vil dine barnedokumenter representere det faktum at en bestemt bruker hadde vurdert et bestemt innlegg-de er ikke noe mer enn en user_id, post_id og en vurdering: en join-tabell i relasjonsdatabase lingo.

Ved hjelp av en forelder / barn relasjoner og has_child kan du enkelt finne alle innleggene favorisert av en bruker samtidig som brukerne kan søke gjennom sine favoritter basert på innlegg innhold, dato eller andre av et innlegg attributter eller noen av de underordnede element egenskaper. Å legge til et element i listen over rangerte elementer er billig – det krever bare indeksering av et veldig lite rating element.

med disse dokumentene

denne spørringen

finner bare «bolivia vurdert 4» siden det er det eneste innlegget som nevner bolivia som har blitt vurdert over 3 av brukeren vi er interessert i. Toppnivåspørringen på tittel gjelder for innleggene, hvor spørringen i filteret has_child beskriver forhold som barna må samsvare med(i dette tilfellet må de tilhøre en bestemt bruker og ha minst en viss vurdering).

Bestilling

hva has_child ikke lar deg gjøre er å bestille basert på attributter til barna eller returnere attributter til barnet. Hvis du ønsket å bestille en brukers rangerte innlegg basert på når de ble vurdert eller ved å redusere vurdering, kan du søke mot innlegg / vurdering direkte, men du vil kanskje bruke noen søk critera til innleggene også. For eksempel kan det være lurt å bare finne vurdert innlegg på et bestemt emne(fortsatt bestilling av vurdering brukeren ga). Med has_child er du ute av lykke. Nestede dokumenter hjelper heller ikke.

Fra 0.19.10 kan du bruke filteret has_parent. Dette fungerer nesten nøyaktig det samme som har barn, men lar deg angi en spørring mot de overordnede elementene i stedet. Denne spørringen returnerer rangeringer etter bruker 1234, på innlegg hvis tittel samsvarer med» bolivia», i avtagende score rekkefølge

dette returnerer vurderingsobjektene-du må da hente de tilsvarende innleggene med en egen spørring.

Faking it

hvis du sitter fast på en eldre versjon av elasticsearch, kan du få det meste av veien der med top_children. Som dokumentasjonen sier top_children spør først barnedokumentene og samler dem deretter inn i overordnede dokumenter. I vårt eksempel betyr dette at elasticsearch først vil finne vurderingsdokumentene som samsvarer med søket vårt. Da vil det matche hver vurdering til sin overordnede innlegg, samle duplikat innlegg der de finnes.

den fiddly bit med topp barn er at elasticsearch ikke vet på forhånd hvor mange dokumenter det vil miste når aggregering skjer. I dette tilfellet er det enkelt fordi to forskjellige rangeringer av samme bruker alltid samsvarer med to forskjellige innlegg, så vi trenger ikke å bry deg med factor og incremental_factor innstillinger fordi aggregeringsfasen aldri gjør noe. På samme måte spiller ikke scoremodus heller. Hvis du trenger å gi en nøyaktig telling av det totale antall resultater du trenger bare å sette factor stor nok til at den første feie elasticsearch gjør av barnet dokumenter finner dem alle. Hvis du vet at brukeren har 500 rangerte elementer på listen, og du ber om de første 10 elementene, bør en faktor på 50 gjøre trikset. Faktor trenger bare å være en øvre grense-du trenger ikke å vite nøyaktig hvor mange elementer brukeren har på sin liste (som kan være vanskelig å trene uten et eget elastisk søk hvis brukeren søker en bestemt delmengde av sine karakterer).

hva du får etter alt dette er en liste over overordnede dokumenter (innlegg) sortert etter spørringen score av barn dokumenter (karakterer). For å oppnå det opprinnelige målet om å sortere innleggene basert på attributtene til barnedokumentene, trenger vi bare å sikre at denne spørr-poengsummen har riktig verdi. Hvis du for eksempel har top_children spørringsbryt en custom_score spørring slik at du har kontroll på hva poengsummen for hvert barn er.

med de samme dokumentene i indeksen returnerer denne spørringen innleggene som bruker 1234 har vurdert, sortert etter deres vurdering:

vi kjører en top_children spørring, så det første vi må gjøre er å si hva slags barn vi vurderer (vurdering). Deretter gir vi spørringen som finner disse barna. Dette er en custom_score – spørring, som pakker inn en filtered – spørring. filtered – spørringen sikrer at vi bare finner vurderinger gitt av brukeren vi er interessert i, og deretter gjør script – elementet poengsummen til vurderingsdokumentet vurdering selv, slik at vi får innleggene våre sortert etter vurdering. Funkiness med backslashes er bare fordi jeg prøver å inkludere et bokstavelig enkelt sitat i en skallvennlig streng avgrenset av enkelt anførselstegn – den faktiske json som vi sender, har bare "script": "doc.value".

Ruby fun

Dessverre støtter dekkbiblioteket egentlig ikke noe av dette morsomme ting for øyeblikket – det er litt av et moratorium på denne typen funksjon blir lagt til fordi for øyeblikket hver eneste liten spørretype og alternativ ender opp med å være separate metoder spredt over dekk, som vedlikeholderen forståelig nok ikke liker. Du kan liksom hacke den i skjønt.

Dekk tillater ikke at du angir et dokuments overordnede id når du indekserer. Dette er greit å legge til og blir bare holdt opp av nevnte moratorium. Min gaffel legger til denne evnen. Med det ender du med

den neste biten av ulykke er at dekkets autoindeksopprettelse antar en type per indeks, men for at et foreldre/barnforhold skal eksistere, må begge typer være i samme indeks. Jeg har endt opp med å gjøre noe sånt som dette for å lage mine indekser.

som ikke er fullt så vakker, men får jobben gjort.

Til Slutt må du faktisk gjøre spørringen. I fravær av top_children faktisk å være en del av tires api, kan du fudge det som så

denne lille biten av ubehag bygger opp spørringen som en hash og skyver den deretter inn i dekk mens den ser den andre veien. Selvfølgelig kan du strukturere det på en slik måte at det er enkelt å legge til andre forhold (enten På Post eller På Vurdering) til søket. Du kan også bygge opp json manuelt og bruke Post.search :payload => my_json(det er en feil med nyttelastalternativet som kolliderer med tire-contribs logger-utvidelse)

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert.