Tutorial #010: Building Dynamic Queries using Bloomreach XM and XIN Mods
in Bloomreach XM Tutorials,
by Marnix Kok
last published on 15 August 2022
In this video we're going to talk about writing more complex dynamic queries for Bloomreach XM using the XIN Mods Query API.
While the query we wrote in the last tutorial works just fine, often times a query is based on dynamic information, like the category someone is in, or perhaps filters and search terms on a search page.
There are two main ways you can make your queries more dynamic:
- inline if-statements; and
- building your query by chaining clauses together
We're going to have a look at both of them, check out the video below.
Code for if-then-else query clause
it("should list recipes with a certain ingredient", async () => { const conn = xinmods.connectTo("http://localhost:8080", "admin", "admin"); const options = { // true? then we must .and() // false? then we must .or() all: false, keywords: ['garlic', 'onion', 'curry', 'powder'] }; const whereClause = conn.newClause("where"); const keywordClause = options.all ? whereClause.and() : whereClause.or(); for (const keyword of options.keywords) { keywordClause.contains("xinmods:ingredient/xinmods:string", keyword); } const queryStr = ( conn.newQuery() .type("xinmods:recipe") .includePath("/content/documents/recipes") .where() .if( options.all === true, (q) => { q.or() .contains("xinmods:ingredient/xinmods:string", "garlic") .contains("xinmods:ingredient/xinmods:string", "onion") .end() }, (q) => { q.and() .contains("xinmods:ingredient/xinmods:string", "garlic") .contains("xinmods:ingredient/xinmods:string", "onion") .end() } ) .orderBy("xinmods:title") .build() ); console.log("Query Str: ", queryStr); // const queryResponse = await conn.executeQuery(queryStr); // // for (const resultDoc of queryResponse.documents) { // console.log("result: ", resultDoc.items.title); // } });
Chaining query clauses
it("should list recipes with a certain ingredient", async () => { const conn = xinmods.connectTo("http://localhost:8080", "admin", "admin"); const options = { // true? then we must .and() // false? then we must .or() all: false, keywords: ['garlic', 'onion', 'curry', 'powder'] }; const whereClause = conn.newClause("where"); const keywordClause = options.all ? whereClause.and() : whereClause.or(); for (const keyword of options.keywords) { keywordClause.contains("xinmods:ingredient/xinmods:string", keyword); } const queryStr = ( conn.newQuery() .type("xinmods:recipe") .includePath("/content/documents/recipes") .where(whereClause) .orderBy("xinmods:title") .build() ); console.log("Query Str: ", queryStr); // const queryResponse = await conn.executeQuery(queryStr); // // for (const resultDoc of queryResponse.documents) { // console.log("result: ", resultDoc.items.title); // } });