xquery order by date Time - datetime

Say I have the following documents in my database: a_doc1, a_doc2, b_doc1, and b_doc2
All these documents are of the following format
<doc>
....
<updatedTime>2011-02-07T14:41:02.133-05:00</updatedTime>
....
</doc
>
The value of the "updatedTime" element is inserted when the document is created using the fn:current-dateTime()
Now I am trying to do the following:
find all documents whose name starts with "a_"
order these documents by their <updatedTime> element in descending order
Return the first document name from the descending order
I tried the following:
for $doc_name in db:list()
where fn:starts-with($doc_name, 'a_')
order by xs:dateTime(doc($doc_name)/updatedTime) descending
return $doc_name
Say "a_doc1" is created at "2011-02-07T14:40:00.78-05:00" and "a_doc2" is created at "2011-02-07T14:41:02.133-05:00", the desired output is a_doc2. In short the document name(starting with a_) of the most recent document created must be returned.
When I try my sample code, the output returned is : [a_doc1, a_doc2].
The expected output is: [a_doc2, a_doc1].
Thanks,
Sony

order by dateTime(doc($doc_name)/updatedTime/text())
Instead of this use:
order by xs:dateTime(doc($doc_name)/updatedTime)

you should use (xs: http://www.w3.org/2001/XMLSchema):
xs:dateTime($arg as xs:anyAtomicType?) as xs:dateTime?
Example:
xs:dateTime("1999-12-31T12:00:00")
instead of (fn: http://www.w3.org/2005/xpath-functions)
fn:dateTime($arg1 as xs:date?, $arg2 as xs:time?) as xs:dateTime?
Example:
fn:dateTime(xs:date("1999-12-31"), xs:time("12:00:00"))

Related

Gremlin hasId using property of parent

I would like to filter out by an id. The value of the id is on a property of the parent. Example:
g.V('1234')
.as('parent')
.out()
.has(id, parent.childId). <--- how do I get the parent id?
How would one approach this?
The closest I've been able to get is the following query, but it seems to ignore the has and simply returns all results of out.
g.V('123')
.as('parent')
.values('childId')
.as('childIdValue')
.select('parent')
.out('hasChild')
.has('id', select('childIdValue'))
EDIT
It works as expected when a vertex property other than the Id is used. Example:
g.V('123')
.as('parent')
.values('childId')
.as('childIdValue')
.select('parent')
.out('hasChild')
.has('childProp', select('childIdValue'))
I've tried all variations of id that I can think of. 'id', id, id().
You can compare an ID using a where by approach. For example something like:
where(eq('parent')).by('childProp').by('childId')

Update dictionary key inside list using map function -Python

I have a dictionary of phone numbers where number is Key and country is value. I want to update the key and add country code based on value country. I tried to use the map function for this:
print('**Exmaple: Update phone book to add Country code using map function** ')
user=[{'952-201-3787':'US'},{'952-201-5984':'US'},{'9871299':'BD'},{'01632 960513':'UK'}]
#A function that takes a dictionary as arg, not list. List is the outer part
def add_Country_Code(aDict):
for k,v in aDict.items():
if(v == 'US'):
aDict[( '1+'+k)]=aDict.pop(k)
if(v == 'UK'):
aDict[( '044+'+k)]=aDict.pop(k)
if (v == 'BD'):
aDict[('001+'+k)] =aDict.pop(k)
return aDict
new_user=list(map(add_Country_Code,user))
print(new_user)
This works partially when I run, output below :
[{'1+952-201-3787': 'US'}, {'1+1+1+952-201-5984': 'US'}, {'001+9871299': 'BD'}, {'044+01632 960513': 'UK'}]
Notice the 2nd US number has 2 additional 1s'. What is causing that?How to fix? Thanks a lot.
Issue
You are mutating a dict while iterating it. Don't do this. The Pythonic convention would be:
Make a new_dict = {}
While iterating the input a_dict, assign new items to new_dict.
Return the new_dict
IOW, create new things, rather than change old things - likely the source of your woes.
Some notes
Use lowercase with underscores when defining variable names (see PEP 8).
Lookup values rather than change the input dict, e.g. a_dict[k] vs. a_dict.pop(k)
Indent the correct number of spaces (see PEP 8)

Xquery/eXist-db - iterating over a collection +/- 3 positions from current document

In eXist-db I have hundreds of documents in /db/apps/foo/resources/documents like so:
...
BNF9992-J305-1.xml
BNF9992-J305-5.xml
BNF9992-J308-9.xml
BNF9992-J310-8.xml
BNF9992-J311-1.xml
BNF9992-J312-6.xml
BNF9992-J312-7.xml
BNF9992-J315-9.xml
BNF9992-J316-2.xml
BNF9992-J317-2.xml
BNF9992-J319-3.xml
...
Imagine I want to present to the user a list of 3 documents appearing before and after a specific document (based on alpha-numeric sort). So, my 'current document' is BNF9992-J312-7.xml, and I want to show the user something like:
BNF9992-J310-8.xml
BNF9992-J311-1.xml
BNF9992-J312-6.xml
BNF9992-J312-7.xml (current document)
BNF9992-J315-9.xml
BNF9992-J316-2.xml
BNF9992-J317-2.xml
Is there a function/method in Xquery 3.1 for iterating up/down a list of documents once they've been retrieved. The most I've been able to do is a simple retrieval of document names from a collection:
for $resource in collection("/db/apps/foo/resources/documents")
let $uri := base-uri($resource)
return util:unescape-uri(replace($uri, ".+/(.+)$","$1"), "UTF-8")
But I don't know how to iterate up and down the list from a given document.
Perhaps writing the list into nodes and applying a formula to node ordinals?
Many thanks.
If this were a list of strings $list, and the "current string" is $s, then I would do
let $i := index-of($list, $s)
return subsequence($list, $i - 3, 7)
I'm not sure whether the fact that you have a list of documents (rather than strings) changes this.

cts search to test if the element is not available

Below is the XML structure where I want to get the entries for which element co:isbn is not available:-
<tr:trackingRecord xmlns:tr="https://www.mla.org/Schema/Tracking/tr"
xmlns:co="https://www.mla.org/Schema/commonModule/co"
xmlns:r="http://www.rsuitecms.com/rsuite/ns/metadata">
<tr:journal>
<tr:trackingDetails>
<tr:entry>
<co:trackingEntryID>2015323313</co:trackingEntryID>
<co:publicationDate>2015</co:publicationDate>
<co:volume>21</co:volume>
</tr:entry>
<tr:entry>
<co:trackingEntryID>2015323314</co:trackingEntryID>
<co:publicationDate>2015</co:publicationDate>
<co:isbn>
<co:entry>NA</co:entry>
<co:value>1234567890128</co:value>
</co:isbn>
</tr:entry>
<tr:entry>
<co:trackingEntryID>2015323315</co:trackingEntryID>
<co:publicationDate>2015</co:publicationDate>
<co:volume>21</co:volume>
<co:isbn></co:isbn>
</tr:entry>
<tr:entry>
<co:trackingEntryID>2015323316</co:trackingEntryID>
<co:publicationDate>2015</co:publicationDate>
<co:volume>21</co:volume>
</tr:entry>
</tr:trackingDetails>
</tr:journal>
</tr:trackingRecord>
Please suggest the cts:query for the same.
If you can edit xml structure, add one attribute in entry element, like
<tr:entry isbnPresent="yes"> for isbn present,
<tr:entry isbnPresent="no"> for isbn absent
and based on these field fire search with,
cts:element-attribute-value
on it.
OR
without editing schema, try like, ,
for $i in cts:search(//tr:entry,"2015")
return if(fn:exists($i//co:isbn)) then () else $i

cts search ignoring index order with cts:element-attribute-reference date

Background
I'm using a cts search in MarkLogic and it is not sorting by the passed sort option.
For example the following produces unsorted results
xdmp:document-insert("/test/test1",<test attrDate="2016-1-10"></test>);
xdmp:document-insert("/test/test2",<test attrDate="2015-1-10"></test>);
xdmp:document-insert("/test/test3",<test attrDate="2017-1-10"></test>);
cts:search(
xdmp:directory("/test/", "infinity")/test,
cts:true-query(),
(
cts:index-order(cts:element-attribute-reference(xs:QName("test"), xs:QName("attrDate")), ("ascending"))
)
);
This returns the following:
<test attrDate="2016-1-10">
</test>
element
<test attrDate="2015-1-10">
</test>
element
<test attrDate="2017-1-10">
</test>
So the correct results but unsorted.
Question
How can I sort by an attribute in a MarkLogic cts query?
Further Background
I have an index set up on that attribute, here is the config:
(This can index be created at http://localhost:8001/ > summary > YOURDATABASE-content > Attribute Range Indexes > Add, although I added it via Roxy)
It turns out this was a simple data issue (which I found in the last 5 seconds before posting this)
2016-01-10 is the 10th of January 2016
2016-1-10 is a malformed string that MarkLogic just ignores

Resources