Dynamic combination search on specific path in BaseX - xquery

I want to perform dynamic combination (AND OR) search on the basis of the provided parameter by the user.
Search Combination Example:
( (title = "United States" or isbn = "2345371242192") and author ="Jhon" )
In the above query each parameter will look on their XPATH e.g. (item/tigroup/title, item/isbn), XPATH not provided by the user, i have to generate XPATH dynamically with search combination
How Combination query can be formed dynamically to pass it to the BaseX?
User can perform any kind of AND OR search, their can be multiple AND OR criteria
Any suggestions much appreciated

With xquery:eval, strings can be evaluated as XQuery expression (see the documentation for more examples):
declare variable $QUERY := 'text()';
db:open('db')//*[xquery:eval($QUERY, map { '': . })]
Please note that it’s very risky to evaluate arbitrary strings as XQuery code. If the string contains user input, malicious strings may be passed on that do unexpected things. In the example above, a malicious string could be a file operation (e.g., file:delete(.)), or a query that runs very long and blocks your system.

Related

In XQuery Marklogic how to sort dynamically?

In XQuery Marklogic how to sort dynamically?
let $sortelement := 'Salary'
for $doc in collection('employee')
order by $doc/$sortelement
return $doc
PS: Sorting will change based on user input, like data, name in place of salary.
If Salary is the name of the element, then you could more generically select any element in the XPath with * and then apply a predicate filter to test whether the local-name() matches the variable for the selected element value $sortelement:
let $sortelement := 'Salary'
for $doc in collection('employee')
order by $doc/*[local-name() eq $sortelement]
return $doc
This manner of sorting all items in the collection may work with smaller number of documents, but if you are working with hundreds of thousands or millions of documents, you may find that pulling back all docs is either slow or blows out the Expanded Tree Cache.
A more efficient solution would be to create range indexes on the elements that you intend to sort on, and could then perform a search with options specified to order the results by cts:index-order with an appropriate reference to the indexed item, such as cts:element-reference(), cts:json-property-reference(), cts:field-reference().
For example:
let $sortelement := 'Salary'
return
cts:search(doc(),
cts:collection-query("employee"),
cts:index-order(cts:element-reference(xs:QName($sortelement)))
)
Not recommended because the chances of introducing security issues, runtime crashes and just 'bad results' is much higher and more difficult to control --
BUT available as a last resort.
ALL XQuery can be dynamically created as a string then evaluated using xdmp:eval
Much better to follow the guidance of Mads, and use the search apis instead of xquery FLOWR expressions -- note that these APIs actually 'compile down' to a data structure. This is what the 'cts constructors' do : https://docs.marklogic.com/cts/constructors
I find it helps to think of cts searches as a structured search described by data -- which the cts:xxx are simply helper functions to create the data structure.
(they dont actually do any searching, they build up a data structure that is used to do the searching)
If you look at the source to the search:xxx apis you can see how this is done.

How to get the data required using Marklogic XQuery cts:search

So, I faced an interview recently with a well known company on Marklogic. He has asked me a question which I couldn't answer. There is an XML example data as below shown.
He asked me how can you get only employee id whose zipcode is 12345 and state is california using search? like cts:search
The thing which came into my mind is write XPath like below but since he asked me using search I couldn't answer
let $x :=//employee/officeAddress[zipCode="38023"]/../employeeId/string()
return $x
xml dataset:
<employees>
<employee>
<employeeId>30004</employeeId>
<firstName>crazy</firstName>
<lastName>carol</lastName>
<designation>Director</designation>
<homeAddress>
<address>900 clean ln</address>
<street>quarky st</street>
<city>San Jose</city>
<state>California</state>
<zipCode>22222</zipCode>
</homeAddress>
<officeAddress>
<address>000 washington ave</address>
<street>bonaza st</street>
<city>San Francisco</city>
<state>California</state>
<zipCode>12345</zipCode>
</officeAddress>
<employee>
</employees>
Using XPath is a natural initial thought for many familiar with XML technologies and starting with MarkLogic. It was what I first started to do when I was just starting out.
Some XPath expressions can be optimized by the database and perform fast and efficiently, but there are also others that cannot and may not perform well.
Using cts:search and the built-in query constructs allows for optimized expressions that will leverage indexes, and allows you to further tune by analyzing xdmp:plan, xdmp:query-meters, and xdmp:query-trace.
An equivalent cts:search expression for the XPath, specifying the path to /employees/employee in the first $path parameter and combining cts:element-value-query with cts:and-query in the second $query parameter would be:
cts:search(/employees/employee,
cts:and-query((
cts:element-value-query(xs:QName("zipCode"), "12345"),
cts:element-value-query(xs:QName("state"), "California") )))/employeeId
You could also use a more generic $path to search against all documents and use an xdmp:element-query() to surround the cts:element-value-query criteria to restrict the search to descendants of the employee element and then XPath into the resulting document(s):
cts:search(doc(),
cts:element-query(xs:QName("employee"),
cts:and-query((
cts:element-value-query(xs:QName("zipCode"), "12345"),
cts:element-value-query(xs:QName("state"), "California") ))
)
)/employees/employee/employeeId
xpath I would have tried (not tested):
/employees/employee[officeAddress/zipCode = '38023' and officeAddress/state = 'California']/employeeId/string()
Note that you can use xdmp:plan on xpath too; it's interesting to see how it works vs cts:search.
In general you're better off putting as much into cts:search as possible vs xpath (and I like xpath!).
The question is a little ambiguous. Are there many employees in one document? Or many employees documents? Both?
Also, don't forget to add the appropriate position indexes, or you won't get much unfiltered help. Look at the plan before and after adding the indexes.
See also https://help.marklogic.com/Knowledgebase/Article/View/queries-constrained-to-elements

Unable to mach strings in sqlite-net query in Greek language

I want to return from sqlite database some strings based on what the user typed. The comparison must be case-insensitive. While my query works for English data, it only works for Greek when all letters are Caps. So I guess that the method ToUpper() performs differently in the query and in the code.
I've narrowed down the problem to the ToUpper() method because when I run it outside of the query to the filter string it performs great for capital letters.
var filterString = filter.Designation?.ToUpper();
var sites = from c in MemoryService.DbContext.db.Table<Site>()
where filterString == null || c.Designation.ToUpper().Contains(filterString)
I think you need to use a culture specific comparison, see this post here.
Compare strings with non-English characters?
This assumes you know what language the compared strings will be typed in.

Substring and Length function in U SQL

I want all records where ParaName matches with tagName. i have tried Length, LEFT and SUBSTRING function, but i think Length,LEFT and SUBSTRING functions are not possible in U-SQL. If possible, what is the syntax??
#var=
SELECT * FROM Table
WHERE ParaName LIKE tagName+"%";
U-SQL emphasizes the use of C# Expressions and methods on .NET types to handle many common cases that SQL achieves with functions.
In this case your type is string (System.String) so methods like StartsWith() and Contains() can be used among many others.
Example: ParmeterName that begins with tagName
WHERE ParameterName.StartsWith( tagName )
Example: ParmeterName that contains with tagName
WHERE ParameterName.Contains( tagName )
There are many examples of using various c# expressions and methods at the official reference site - U-SQL Language Reference. Look under the sub-topic Built-in C# Functions and Operators (U-SQL).

Riak search queries via the java client

I am trying to perform queries using the OR operator as following:
MapReduceResult result = riakClient.
mapReduce("some_bucket", "Name:c1 OR c2").
addMapPhase(new NamedJSFunction("Riak.mapValuesJson"), true).
execute();
I only get the 1st object in the query (where name='c1').
If I change the order of the query (i.e. Name:c2 OR c1) again I get only the first object in query (where name='c2').
is the OR operator (and other query operators) supported in the java client?
I got this answer from Basho engeneer, Sean C.:
You either need to group the terms or qualify both of them. Without a field identifier, the search query assumes that the default field is being searched. You can determine how the query will be interpreted by using the 'search-cmd explain' command. Here's two alternate ways to express your query:
Name:c1 OR Name:c2
Name:(c1 OR c2)
both options worked for me!

Resources