Introduktion till MarkLogic – Del 2, att söka

Share on FacebookShare on Google+Email this to someoneTweet about this on TwitterShare on LinkedIn

Detta är det andra inlägget runt hur du bygger en lösning med MarkLogic NoSQL databas, i det första gick jag igenom hur du skapar en databas, laddar samt uppdatera data.

I detta inlägg tänker jag fokusera på hur du kan söka i de dokumenten, data som vi laddade ,vi har i databasen.

En av, många, fördelar som MarkLogic har är att det är en NoSQL databas med inbyggd sökfunktionalitet. Men vad innebär det?

I många fall så är en av de största utmaningar vi har med vårt data är att få ut något vettigt från det. I många fall vet man inte innan ifall den data man samlat in är relevant att använda, man behöver göra någon form av fri sökning för att få en bättre förståelse.

I den relationella världen, och i vissa NoSQL lösningar, krävs det att man strukturerar upp data i olika tabeller med relationer och så vidare innan det är möjligt att börja söka i det. Detta innebär också att innan jag kan börja göra mina sökningar så måste jag veta i vilka kolumner och tabeller som informationen finns i, jag måste också i fall det ligger i flera olika tabeller veta hur jag skall koppla, joina, ihop dem.

Summa summarum, det är ganska mycket jag måste veta innan jag kan börja söka.

Så låt oss titta på hur MarkLogic löser detta.

MarkLogic hanterar inte relationer eller scheman på samma sätt som en relationsdatabas gör. Varje dokument, ett dokument kan ses som en rad, har sitt eget schema. Det gör att jag inte behöver bestämma i förväg en struktur när jag laddar mitt data.

Sedan så indexeras dokumenten på olika sätt när de skapas, det finns olika typer av index vilka vissa alltid finns där och andra typer behöver jag skapa.

Om du har följt min första post så har du nu en databas med nobelpristagare där vi använder standard inställningar. Detta innebär att vi bara använder de index som skapas automatiskt av MarkLogic när data läses in.

Låt oss nu titta på hur vi kan söka efter information i vår databas, i fall du inte vill skriva av/kopiera koden så kan du ladda hem en workspace fil här, högerklicka på Search part 1.xml och spara ned den lokalt, som kan importeras till Query Console genom att klicka på pilen vid Workspace längs till höger och välja Import Workspace.  Var noga och se till att välja nobelprize i Content Source innan du exekverar koden.

Så om jag vill hitta alla nobelpristagare där ordet nuclear nämns någonstans i alla fälten så kan jag skriva en enkel fråga för det. Det är bara att öppna Query Console, http://localhost:8000/qconsole/ (nu kommer jag att använda localhost i alla exempel men i fall du inte har installerat MarkLogic lokalt på din dator så behöver du byta ut det mot den ip-adress/namn som datorn med installationen har), välja nobelprize i Content Source, skriva nedan kod och sedan klicka på Run (eller trycka ctrl+enter).

cts:search(fn:doc(), ”nuclear”)

Vi kommer då att få tillbaka alla dokument, rader, som någonstans innehåller ordet nuclear

Enkel ordsökning

cts:search är en funktion i vad man kan kalla lågnivå API i MarkLogic som är språket XQuery, i nästa version av MarkLogic, version 8, så kommer det även vara möjligt att använda JavaScript också men mer om det i en framtida bloggpost.

I ovan exempel så returnerade vi hela dokumentet, om vi vill bara se vissa delar så kan vi enkelt göra det. Nedan exempel returnerar hela namnet samt kategori och år från alla dokument som motsvarar vår sökning.

declare namespace np = ”http://marklogic.com/swe/nobel-prize”; 

let $results := cts:search(fn:doc(), ”nuclear”)
for $result in $results
return
  <winner>
    <name>{$result//np:firstname/string(),$result//np:surname/string()}</name
    {$result//np:category,$result//np:year}
  </winner>

Enkel ordsökning med resultat

 

I och med att vi specificerar vilka element som skall visas så behöver vi använda namnespace, detta eftersom vi har lagt in det i dokumenten vid laddning.

Vill jag på samma sätt också specificera vilket element jag skall söka på, till exempel om vi vill se alla nobelpristagare som var verksamma i Sverige när de fick priset så skriver jag följande

declare namespace np = ”http://marklogic.com/swe/nobel-prize”;

let $results := cts:search(fn:doc(), cts:element-word-query(xs:QName(”np:country”),”sweden”, ”case-insensitive”))
for $result in $results
  return
    <winner>
      <name>{$result//np:firstname/string(),$result//np:surname/string()}</name
    {$result//np:category,$result//np:year, $result//np:country}
   </winner>

Enkel ordfråga på element

Hittills så har vi bara sökt efter ett ord, om jag vill hitta alla dokument där ordet nuclear och USA förekommer, och jag vill inte att de skall finnas bredvid varandra, så kan jag göra det genom att skriva följande.

cts:search(fn:doc(), cts:and-query((cts:word-query(”usa”, ”case-insensitive”), cts:word-query(”nuclear”, ”case-insensitive”))))

cts:and-query talar om att båda sökkriterierna måste uppfyllas och cts:word-query är för att söka efter ett ord oavsett var det finns. Jag kan givetvis också specificera vilka element jag skall söka på.

declare namespace np = ”http://marklogic.com/swe/nobel-prize”;

 cts:search(fn:doc(), cts:and-query(
(cts:element-word-query(xs:QName(”np:country”),”sweden”, ”case-insensitive”),
            cts:element-word-query(xs:QName(”np:category”),”physics”, ”case-insensitive”))))

Det går givetvis att kombinera cts:element-word-query och cts:word-query i samma sökning.

declare namespace np = ”http://marklogic.com/swe/nobel-prize”;

 cts:search(fn:doc(), cts:and-query(
(cts:word-query(”max”, ”case-insensitive”),
cts:element-word-query(xs:QName(”np:category”),”physics”, ”case-insensitive”))))

Men om vi vill att bägge orden skall förekomma i samma text men inte precis bredvid varandra, hur söker vi då?

Det vi kan använda då är cts:near-query där vi kan specificera vilka ord och hur långt ifrån varandra de skall max vara. Nedan sökning returnerar alla dokument där orden nuclear och studies förekommer inom tre ord från varandra.

cts:search(fn:doc(),
cts:near-query(
(cts:word-query(”nuclear”), cts:word-query(”studies”)), 3))

Nära ordfråga

Om du skrollar ner till det andra dokumentet så kan du också se en annan inbyggd funktionalitet i MarkLogic, nämligen stemming. För om vi tittar på motivation texten så kan vi se ordet nuclear men inte studies, istället så har vi ordet studying.

Stemming handlar om att hantera böjningar av ord. I detta fall så vet MarkLogic att studying och studies är böjningar av study och därmed samma sak. Det riktigt coola med detta är att MarkLogic stöder förutom engelska ca 15 språk varav svenska är ett av dem. Och givetvis kan jag stänga av stemming när jag söker om jag bara vill hitta ett specifikt ord.

Jag hoppas att du nu har fått en känsla för hur man kan söka efter information i MarkLogic, vi har bara skrapat på ytan och i nästa inlägg kommer jag gå igenom ytterligare sätt som kan göra det ännu enklare.

Vill du läsa mer om cts:search så kan du göra det här:  https://docs.marklogic.com/guide/search-dev/cts_query

Vill du förstå mer om hur MarkLogic fungerar så finns det är mycket bra white paper, Inside MarkLogic Server.

Kommentera gärna med vad du tycker om detta inlägg.

/Mats Stellwall

Share on FacebookShare on Google+Email this to someoneTweet about this on TwitterShare on LinkedIn