How do I retrieve values from a filter query within a CosmosDb stored procedure? - stored-procedures

I'm struggling to work out how to retrieve the property values from a filter query in a CosmosDb stored procedure. I'm sure this must be relatively simple, but just can't seem to find the right combination.
var result = __.chain()
.filter(function(doc) {
return doc.id ==="1stDocId";
})
.map(function(doc) {
return {
id: doc.id,
propertyA: doc.propertyA
};
})
.value();
if(!result.isAccepted) throw new Error("The call was not accepted");
Using the above code, or similar, I'm wanting to retrieve the value of propertyA, and then use it in a second query, and so on.
Using response.setBody to return the value of result at this point, I can see it is sat in an array, but can't work out the correct code to access it.
result[0].PropertyA, result[0][0].PropertyA don't work, can someone point me in the right direction?
I'm able to do this sort of thing using the queryDocuments function, but ultimately my stored procedure needs to execute 5 or 6 select statements, manipulating the retrieved values in between. Utilising nested callbacks seems very messy, and pretty confusing once you're a few levels deep. Is there a better way?
Thanks.

Well I gave in, and wrote the procedure using nested callbacks and 'queryDocuments'. Since at one point my procedure requires a switch statement, which either performs a db lookup, or provides a hard value, I had to duplicate the rest of the queryDocument calls in the db lookup branch callback, which feels plain wrong.
However, whilst not being pretty, my stored procedure now works, returning the correct values in all cases.

Related

Dexie eachUniqueKey and Where Clause

I'm developing an application in Quasar/Electron and using Dexie/IndexedDB for my database. I want to find all distinct records in the database that contain both my Event ID and a Dog ID (both key indexed fields). I am able to do this with the following code:
await myDB.runTable
.orderBy('[fk_event+fk_dog]')
.eachUniqueKey((theDuo) => {
this.runsArray.push({eventID: theDuo[0], dogID: theDuo[1]})
})
I'm using a combined key which is working well. However, I need to have more of the records than just the keys. I need a few more fields, is this possible?
I was trying to get records with the unique key function while also using the where function, but that doesn't seem to work.
I need to get all the unique (distinct?) dogs in the table that are in a particular event. And also get their corresponding information. I'm not sure if there is a better, more efficient way to do this? I can always pull out all the records and loop through them to build a custom array, I was just hoping to do this at the table read level. (yeah I'm still in tables/records even though these are collections etc. :p ).
Even the above code gives me all the events, and I can pull out what I need with a filter. I just was thinking it would be faster and more efficient to do it at the read level.
this.enteredRuns = this.runsArray.filter((theEvent) => {
return ( (theEvent.eventID == this.currentEventID) )
})
Try
await myDB.runTable
.orderBy('[fk_event+fk_dog]')
.clone({unique: "unique"})
.toArray()
I know this isn't documented but it should do the work to use unique cursor while still extracting the whole objects and not just the keys. You cannot combine with where but you could use .filter. Just be aware that not all records with be scanned as it will jump over records with same keys - selecting the first visited records only.

PagedResultList .size() and .getTotalCount() return different values in grails gorm

I have the following code
PagedResultList res = myService.getPage(paginateParams, ...)
println res.size() // returns 2
println res.getTotalCount() // returns 1
getPage looks like:
def criteria = MyDomain.createCriteria()
criteria.list(max: paginateParams.max, offset: paginateParams.offset) { // max is 10, offset is 0, sortBy is updatedAt and sortOrder is desc
eq('org', org)
order(paginateParams.sortBy, paginateParams.sortOrder)
}
why do the two method return different values? The documentation doesn't explain the difference, but does mention that getTotalCount is for number of records
currently on grails 2.4.5
edits:
println on res prints out:
res: [
com.<hidden>.MyDomain: 41679f98-a7c5-4193-bba8-601725007c1a,
com.<hidden>.MyDomain: 41679f98-a7c5-4193-bba8-601725007c1a]
Yes, res has a SINGLE object twice - that's the bug I'm trying to fix. How do I know that? I have an primary key on MyDomain's ID, and when I inspect the database, it's also showing one record for this particular org (see my criteria)
edit 2: I found this comment (http://docs.grails.org/2.4.5/ref/Domain%20Classes/createCriteria.html)
listDistinct If subqueries or associations are used, one may end up
with the same row multiple times in the result set. In Hibernate one
would do a "CriteriaSpecification.DISTINCT_ROOT_ENTITY". In Grails one
can do it by just using this method.
Which, if I understand correctly, is their way of saying "list" method doesn't work in this scenario, use listDistinct instead but then they go on to warn:
The listDistinct() method does not work well with the pagination
options maxResult and firstResult. If you need distinct results with
pagination, we currently recommend that you use HQL. You can find out
more information from this blog post.
However, the blog post is a dead link.
Related: GORM createCriteria and list do not return the same results : what can I do?
Not related to actual problem after question edited but this quote seems useful
Generally PagedResultList .size() perform size() on resultList property (in-memory object represent database record), while .getTotalCount() do count query against database. If this two value didn't match your list may contain duplicate.
After viewing related issues (GORM createCriteria and list do not return the same results : what can I do?) I determined that there were several approaches:
Use grails projection groupBy('id') - doesn't work b/c i need the entire object
USe HSQL - Domain.executeQuery - actually this didn't work for my scenario very well because this returns a list, whereas criteria.list returns a PagedResultList from which I previously got totalCount. This solution had me learning HSQL and also made me break up my existing logic into two components - one that returned PagedResultList and one that didn't
Simply keep a set of IDs as I process my PagedResultList and make sure that I didn't have any duplicates.
I ended up going with option 3 because it was quick, didn't require me to learn a new language (HSQL) and I felt that I could easily write the code to do it and I'm not limited by the CPU to do such a unique ID check.

Grails findById( null ) returning "random" result

I found a very strange behavior in our grails application today that i want to share with you.
We are using grails 2.3.11 on mysql 5.1.48.
We had a DomainObject.findById( id ) in one of your Controller actions.
We failed to check the id for a null value so DomainObject.findById( null )
would be called when no id is passed as an argument.
Normally DomainObject.findById( null )
will return null but there is a special condition that will yield other results!
If the controller action called before that inserted a new record in the database (lets call it Object B), regardless of the domain object stored, the DomainObject.findById( null ) will find the DomainObject with the same Id the Object B got on insert.
So when the controller action called before saved anything the findById(null) will return a row. And that row will have the same id the last inserted element got.
I am totally aware that using findById(null) is not the desired way to do it but I was quite shocked about the results it yielded. But returning any seemingly "random" result seems very strange to me.
I also want to note that DomainObject.get(null) will not suffer from this problem.
Anybody else witnessed this?
There is an active Jira pointing in this direction: https://jira.grails.org/browse/GRAILS-9628 but its not really describing this issue.
We don't really support passing null as an argument to a dynamic finder like that. Dynamic finders have explicit support for querying by null. Instead of DomainClass.findByName(null) you would call DomainClass.findByNameIsNull(). If you have a reference that may or may not be null, instead of passing that as an argument to a dynamic finder, the code can almost always be made cleaner by writing a criteria query or a "where" query that has a conditional in it.
I hope that helps.
Thx for your information scot.
I have further details. This behaviour is also altered by the underlying database.
While mysql suffers from this, maria-db (a mysql clone) does not!
So what happens is bound to the underlying database system.
That should not happen to an abstraction layer ....

Hydrating Database

I am new to learning and understanding how Hydration works, just wanted to point that out first. I'm currently able to Hydrate Select and Insert queries without any problems.
I am currently stuck on trying to Hydrate Update queries now. In my entity I have setup the get/set options for each type of column in my database. I've found that the ObjectProperty() Hydrator works best for my situation too.
However whenever I try to update only a set number of columns and extract via the hydrator I am getting errors because all the other options are not set and are returning null values. I do not need to update everything for a particular row, just a few columns.
For example in my DB Table I may have:
name
phone_number
email_address
But I only need to update the phone_number.
$entity_passport = $this->getEntityPassport();
$entity_passport->setPrimaryPhone('5551239876');
$this->getTablePassport()->update($this->getHydrator()->extract($entity_passport), array(
'employeeid' => '1'
));
This returns an error because setName() and setEmailAddress() are not included in this update and the query returns that the values cannot be null. But clearly when you look at the DB Table, there is data already there. The data that is there does not need to be changed either, only in this example does the PrimaryPhone() number.
I've been looking and reading documentation all over the place but I cannot find anything that would explain what I am doing wrong. I should note that I am only using Zend\Db (Not Doctrine).
I'm assuming I've missed something someplace due to my lack of knowledge with this new feature I'm trying to understand.
Perhaps you don't Hydrate Update queries... I'm sort of lost / confused. Any help would be appreciated. Thank you!
I think you're having a fundamental misconception of hydration. A hydrator simply populates an entity object from data (hydrate) and extracts data from an entity object (extract). So there are no separate hydrators for different types of queries.
In your update example you should first retrieve the complete entity object ($entity_passport) and then pass it to the TableGateway's update method. You would retrieve the entity by employeeid, since that's the condition you're using to update. So something like this:
$entity_passport = $passportMapper->findByEmployeeId(1);
$entity_passport->setPrimaryPhone('5551239876');
$this->getTablePassport()->update($this->getHydrator()->extract($entity_passport), array(
'employeeid' => $entity_passport->getId()
));
This is assuming you have some sort of mapper layer. Otherwise you could use your passport TableGateway (I assume that's what getTablePassport() returns, no?).
Otherwise, if you think retrieving the object is too much overhead and you just want to run the query you could use just a \Zend\Db\Sql\Sql object, ie:
$sql = new \Zend\Db\Sql\Sql($dbAdapter);
$update = $sql->update('passport')
->set(array('primary_phone' => $entity_passport->getPrimaryPhone()))
->where(array('employeeid' => $employeeId));
Edit:
Maybe it was a mistake to bring up the mapper, because it may cause more confusion. You could simply use your TableGateway to retrieve the entity object and then hydrate the returned row:
$rows = $this->getTablePassport()->select(array('employeeid' => 1));
$entity_passport = $this->getHydrator($rows->current());
[...]
Edit 2:
I checked your gist and I noticed a few things, so here we go:
I see that your getTablePassport indeed does return an object which is a subclass of TableGateway. You have already set up this class for it to use a HydratingResultset. This means you don't need to do any manual hydrating when retrieving objects using the gateway.
You also already implemented a Search method in that same class, so why not just use that? However I would change that method, because right now you're using LIKE for every single column. Not only is it very inefficient, but it will also give you wrong results, for example on the id column.
If you were to fix that method then you can simply call it in the Service object:
$this->getTablePassport->Search(array('employeeid' => 1));
Otherwise you could just implement a separate method in that tablegateway class, such as
public function findByEmployeeId($employeeId)
{
return $tableGateway->select(array('employeeid' => $employeeId));
}
This should already return an array of entities (or one in this specific case). P.S. make sure to debug and check what is actually being returned when you retrieve the entity. So print_r the entity you get back from the PassportTable before trying the update. You first have to make sure the retrieval code works well.

Erlang and the records

What is wrong in this code?
I was expected "titi" in person.name but I still have "toto"!
More explicitly, how to modify a record in a function?
init1()->
S=#person{name="toto"}, %record creation and field setting
fct(S),
io:format("~s~n",[S#person.name]).
fct(R)->
R#person{name="titi"}. %record updating
You need to get a result of fct():
init1()->
S=#person{name="toto"}, %record creation and field setting
S2 = fct(S), % Get updated record
io:format("~s~n",[S2#person.name]).
fct(R)->
R#person{name="titi"}. %record updating
Bertaud, I think you are getting ahead of yourself a bit. You really need to understand the basics of immutability before you write any more code. (i.e. "variables" do not vary : you can only assign a value to them once.) I suggest you read the free online guide "Learn You Some Erlang For Great Good", at http://learnyousomeerlang.com/. The section that covers the basics of variables is http://learnyousomeerlang.com/starting-out-for-real#invariable-variables.
It is impossible to stress too much that all data in Erlang is immutable. So to do something like in your original question you need to modify it like #hdima did. The record is not updated but rewritten. In the same way there is no global data in Erlang, all data belongs to a process. This is even true of ETS tables as they basically behave like a process, albeit a built-in one without explicit communication.
So if you use the process dictionary or an ETS table the data itself can never be updated, only the dictionary/table. This means that to modify some data in the dictionary/table you basically have to:
"Read" the data
Update the data making new data
"Write" the new back into the dictionary/table
Without writing the new data back into the dictionary/table it will be lost, as your new data was.
Within fct(), you're not mutating the record, but you're returning a new value for the record, which needs to be used further. If you're calling fct(S), without handling the return value, then you'll lose that new value ("titi").

Resources