I have Xml structures coming like this below. I will have to count the installations on the same date and list them. So I will have to find count by InstallDate and return in XQuery to be used in Marklogic query.
<PcDetail>
<Installations>
<Installation>
<Type>pc</Type>
<purchased>Y</purchased>
<InstallDate>2020-10-01T00:00:00:000Z</InstallDate>
</Installation>
<Installation>
<Type>pc</Type>
<purchased>Y</purchased>
<InstallDate>2020-10-01T00:00:00:000Z</InstallDate>
</Installation>
<Installation>
<Type>pc</Type>
<purchased>Y</purchased>
<InstallDate>2020-10-02T00:00:00:000Z</InstallDate>
</Installation>
<Installation>
<Type>pc</Type>
<purchased>Y</purchased>
<InstallDate>2020-10-02T00:00:00:000Z</InstallDate>
</Installation>
<Installation>
<Type>pc</Type>
<purchased>Y</purchased>
<InstallDate>2020-10-02T00:00:00:000Z</InstallDate>
</Installation>
</Installations>
If you wish to group, count and list the Installation by date in MarkLogic server, see below MarkLogic XQuery dialect:
for $d in distinct-values(doc()//InstallDate)
let $i := doc()//Installation[InstallDate = $d]
order by $d
return <Installations Date="{$d}" Count="{count($i)}">
{
for $install in $i
return $install
}</Installations>
In a transaction-driven environment, you should utilise MarkLogic performant search engine:
for $vt in cts:value-tuples(
(cts:element-reference(xs:QName( 'InstallDate'))
),("item-frequency")
)
return "Installation on " || $vt[1] || " total count: " || cts:frequency($vt)
It's pretty straightforward even in XQuery 1.0
let $installations := $xml/PcDetail/Installations/Installation
for $date in fn:distinct-values($installations/InstallDate)
let $installationsOnDate := $installations[InstallDate = $date]
let $c := count($installationsOnDate)
return $date || ':' || $c || ':' || string-join($installationsOnDate/type,', ')
Related
I want to convert CSV to XML using XQuery on BaseX (currently using BaseX v9.4.1). With columns tab separated the CSV file Configuration.tsv (input) looks like this:
Datasets Autosar Fibex TSS0001 TSS0002 TSS0003
DS0001 AutosarFoo01.arxml FibexFoo01.xml x x
DS0002 AutosarFoo02.arxml FibexFoo02.xml x x
DS0003 AutosarFoo03.arxml FibexFoo03.xml x x
The script has tssid as input parameter. Setting tssid := TSS0001 the expected output XML is:
<database name="DS0001" autosar="AutosarFoo01.arxml" fibex="FibexFoo01.arxml"/>
<database name="DS0002" autosar="AutosarFoo02.arxml" fibex="FibexFoo02.arxml"/>
<database name="DS0003" autosar="AutosarFoo03.arxml" fibex="FibexFoo03.arxml"/>
and with tssid := TSS0003:
<database name="DS0002" autosar="AutosarFoo02.arxml" fibex="FibexFoo02.arxml"/>
<database name="DS0003" autosar="AutosarFoo03.arxml" fibex="FibexFoo03.arxml"/>
The script works fine but the third attribute value (fibex) is missing, so the output looks differently like this:
<database name="DS0001" autosar="AutosarFoo01.arxml" fibex=""/>
<database name="DS0002" autosar="AutosarFoo02.arxml" fibex=""/>
<database name="DS0003" autosar="AutosarFoo03.arxml" fibex=""/>
or with tssid := TSS0003:
<database name="DS0002" autosar="AutosarFoo02.arxml" fibex=""/>
<database name="DS0003" autosar="AutosarFoo03.arxml" fibex=""/>
I cannot find something wrong with this code ?!? :
xquery version "3.1" encoding "utf-8";
declare namespace test="unittest";
declare namespace map="http://www.w3.org/2005/xpath-functions/map";
declare variable $test:tssid := 'TSS0003';
declare variable $test:testsuitesfile := '/Users/ms/Projekte/UnitTests/Configuration.tsv';
declare variable $test:options := map { 'header' : 'yes', 'format' : 'attributes', 'separator' : 'tab' };
declare variable $test:xml := csv:doc($test:testsuitesfile,$test:options);
(: get the positions :)
declare variable $test:positionDataId := 1 ;
declare variable $test:positionTssCheck := $test:xml/csv/record[position() = 1]/entry[text() = $test:tssid]/count(./preceding-sibling::entry) + 1 ;
declare variable $test:positionAutosar := $test:xml/csv/record[position() = 1]/entry[text() = 'Autosar']/count(./preceding-sibling::entry) + 1 ;
declare variable $test:positionFibex := $test:xml/csv/record[position() = 1]/entry[text() = 'Fibex']/count(./preceding-sibling::entry) + 1 ;
declare variable $test:dbsetbycsv as map(*) := map:merge(for $record in $test:xml/csv/record[entry[position() = $test:positionTssCheck and text()='x']] return map:entry($record/entry[position() = $test:positionDataId]/text(),<database name="{$record/entry[position() = $test:positionDataId]/text()}" autosar="{$record/entry[position() = $test:positionAutosar]/text()}" fibex="{$record/entry[position() = $test:positionFibex]/text()}"/>));
declare variable $test:dbset := $test:dbsetbycsv;
declare function test:dump() {
for-each(
map:keys($test:dbset),
function($k) {
$test:dbset($k)
}
)
};
let $result := test:dump()
return($result)
It seems that
$xml/csv/record[entry[#name = $tssid and . = 'x']] ! <database name="{entry[#name = 'Datasets']}" autosar="{entry[#name = 'Autosar']}" fibex="{entry[#name = 'Fibex']}"/>
might suffice, given that the entry elements have name attributes.
It's a bug. Fixed now with BaseX 9.4.3 beta.
I'm just starting to learn XQuery and I want that it shows me the number of festivals with genre (genero) is the same as "metal". I can't get the total number of them, only separately.
Xquery
for $b in //festival
where $b/#genero="Metal"
return <prueba>{count ($b/#genero="Metal"), $b//nombre}</prueba>
XML
<Festivales>
<festival genero="Metal">
<informacion>
<nombre>Resurrection Fest</nombre>
<fecha_inicio>2020-07-01</fecha_inicio>
<fecha_fin>2020-07-04</fecha_fin>
</festival>
<festival genero="Rock-Heavy Metal">
<informacion>
<nombre>Rock the Night</nombre>
<fecha_inicio>2020-06-26</fecha_inicio>
<fecha_fin>2020-06-27</fecha_fin>
</festival>
<festival genero="Hardcore">
<informacion>
<nombre>Ieperfest</nombre>
<fecha_inicio>2020-07-03</fecha_inicio>
<fecha_fin>2020-07-05</fecha_fin>
</informacion>
</festival>
<festival genero="Metal">
<informacion>
<nombre>Download UK</nombre>
<fecha_inicio>2020-06-12</fecha_inicio>
<fecha_fin>2020-06-14</fecha_fin>
</informacion>
</festival>
</Festivales>
Result
<prueba>1<nombre>Resurrection Fest</nombre>
</prueba>
<prueba>1<nombre>Hellfest</nombre>
</prueba>
<prueba>1<nombre>Download UK</nombre>
</prueba>
Thanks!
for $b in //festival[#genero="Metal"]
let $n := $b/informacion/nombre/text()
return
<prueba>
{
<cnt>{count(//festival[#genero="Metal"]/informacion/nombre[. = $n])}</cnt>
, $b/informacion/nombre
}
</prueba>
I have a scenario where I have to find the column name for the tables.
I have a large file having around 50K records
like:
PLACES_OF_INDIA_2 :3432123, :Names Expr=('"Table_Name1".Column_1 || '' '' || "Table_Name2".Column_1 || '' '' || "Table_Name3"."Column_2"'), :Name=BCUDB2."Table_Name1".ATTR_VALUE, :Condition=BCUDB2."Table_Name1".Column_1, :Tables=(ABCXYZ."Table_Name1", ABCXYZ."Table_Name2", ABCXYZ."Table_Name3"), :Keys=ABCXYZ."IT_DIM_ANHBUSCH_37560".(M_113478_PQR(Int), M_113443_PQR(Int), M_113484_PQR(Int), M_113470_PQR(Int), M_113468_PQR(Int)), :Attrs=(Name :456866 = ('"Table_Name1".Column_1 || '' '' || "Table_Name2".Column_1 || '' '' || "Table_Name3"."Column_2"', ABCXYZ."Table_Name1", ABCXYZ."Table_Name2", ABCXYZ."Table_Name3"), PLACES_OF_ORIGIN_WineHierarchy_2 :490064736 = ABCXYZ."Table_Name1".ATTR_VALUE)
So I want to extract the columns with the line number used for the tables in the file. I have list of tables in separate file like
Table_Name1
Table_Name2
Table_Name3
and I want the output like
1,Column_1
1,Column_2
1,Column_3
Could you please check this
how to reproduce in query builder this
AND LENGTH( CONCAT_WS('', lsc.door_code, lsc.alarm_code, lsc.service_code, lsc.master_log) ) > 0"
I try like this
$orX = $qb->expr()->orX();
$orX
->add($qb->expr()->length('lsc.doorCode > 0'))
->add($qb->expr()->length('lsc.alarmCode > 0'))
->add($qb->expr()->length('lsc.serviceCode > 0'))
->add($qb->expr()->length('lsc.masterLog > 0'));
$qb->andWhere($orX);
have error:
[Syntax Error] line 0, col 549: Error: Expected Doctrine\ORM\Query\Lexer::T_CLOSE_PARENTHESIS, got '>'
and my query
SELECT
CONCAT(
IFNULL(location.name, ''),' (',IFNULL(location.streetAddress, ''),' ',IFNULL(location.staircase, ''),' ',IFNULL(location.flatNumber, ''),' ',IFNULL(location.postal, ''),' ',IFNULL(location.postOffice, ''),')') as address,
lsc.doorCode,
lsc.serviceCode,
lsc.alarmCode,
lsc.masterLog
FROM AppBundle:LocationServiceCompany lsc INNER JOIN lsc.location location WHERE lsc.serviceCompany = :sc AND (LENGTH(lsc.doorCode > 0) OR LENGTH(lsc.alarmCode > 0) OR LENGTH(lsc.serviceCode > 0) OR LENGTH(lsc.masterLog > 0))
how to use length ?
I came here because I had similar problem with using length in query builder.
I tried ($qb->expr()->length('lsc.doorCode > 0') as suggested above but it did not work. The SQL output of this is "LENGTH(lsc.doorCode > 0)" which throws an error.
My solution to this problem is:
$qb->expr()->gt($qb->expr()->length('lsc.doorCode'), 0)
which generates "LENGTH(lsc.doorCode) > 0" that is correct SQL syntax.
You have a typo here:
$orX = $qb->expr()->orX();
$orX
->add($qb->expr()->length('lsc.doorCode > 0')); <--
->add($qb->expr()->length('lsc.alarmCode > 0'))
->add($qb->expr()->length('lsc.serviceCode > 0'))
->add($qb->expr()->length('lsc.masterLog > 0'));
$qb->andWhere($orX);
remove the ; and get rid of the syntax error.
And for the concat length, you can try something like this:
$query->andWhere("LENGTH( CONCAT_WS('', lsc.door_code, lsc.alarm_code, lsc.service_code, lsc.master_log) ) > 0")
After the update
You can run native SQL queries with Doctrine like mentioned here:
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/native-sql.html#the-nativequery-class
For reference:
<?php
use Doctrine\ORM\Query\ResultSetMapping;
$rsm = new ResultSetMapping();
// build rsm here
$query = $entityManager->createNativeQuery('SELECT id, name, discr FROM users WHERE name = ?', $rsm);
$query->setParameter(1, 'romanb');
$users = $query->getResult();
If your updated query works, this would be a way to make it work.
for the below data -
let $x := "Yahooooo !!!! Select one number - "
let $y :=
<A>
<a>1</a>
<a>2</a>
<a>3</a>
<a>4</a>
<a>5</a>
<a>6</a>
<a>7</a>
</A>
I want to get the output as -
`Yahooooo !!!! Select one number - [1 or 2 or 3 or 4 or 5 or 6 or 7]`
In XQuery 3.0, you can use || as a string concatenation operator:
return $x || "[" || fn:string-join($y/a, " or ") || "]"
In XQuery 1.0, you need to use fn:concat():
return fn:concat($x, fn:concat("[", fn:concat(fn:string-join($y/a, " or "), "]")))