Hyperledger Composer Query Access Returned Resource ID - javascript

I had a question regarding the return value of a query in hyperledger composer.
For reference my query:
query findCountOfficer {
description: "find count officer asset given name"
statement:
SELECT org.example.CountOfficer
WHERE (name == _$nameParam)
}
My querying:
let countOfficerRecord = await query('findCountOfficer', {nameParam: countOfficerName})
I am trying to retrieve the ID of the count officer from the count officer record parameter.
Does anyone know how to access the identifier or fields of a resource returned from a query?
Or if not that how to have a query return the employeeId? (i.e. select employeeID)
What I've tried:
When I print countOfficerRecord I get Resource {id=org.carm.CountOfficer#1}
I want to access the 1 ID. However if I call countOfficerRecord.id or countOfficerRecord.employeedId (as employeeId is the identifier in the model file) I get undefined.
As this is a Resource I also tried functions from the documentation such as getIdentifier() and isResource() and got an error that these weren't functions for countOfficerRecord.
Thanks!

If you want to get the identifier then try this
console.log( countOfficerRecord.$identifier)
if you want the whole record of countOfficerRecord
then try this
console.log([countOfficerRecord])

It looks like you are invoking the toString() method on the resource object that you have (either explicitly or implicitly via whatever mechanism you use to print the object). The output you see is the result of that toString invocation and not a JSON respresentation of the object, you can interact with the resource object using it's api's, eg
console.log(countOfficerRecord.getIdentifier());
console.log(countOfficerRecord.name)
The above example references $identifier which isn't a recommended approach as this is an internal field name and could change in the future. You should use the api's of a resource object to obtain information.
The api reference for a resource can be found here
https://hyperledger.github.io/composer/latest/api/common-resource

I tried this and it worked.
Queries usually return an array. Therefore, you first reference the array and then get the identifier.
countOfficerRecord[0].$identifier

Related

Deleting data from a mockapi.io json, with javascript

I am using mockapi.io for my first big learning project(ecomerce) and i can do get, post but seems like not delete. It deletes the row in the admin page table but not the product from the online api. Seems impossible to find info about this issue online, or i just don't know how to ask the right question. Maybe it's not even posible to really delete from a mock api?!
I am geting in the console: http.js:21 DELETE https://6060b8b904b05d0017ba2dfb.mockapi.io/products?id=50 400 (Bad Request)
So it does compose the right link to that specific product, but just doesn't delete it.
function deleteProduct(e) {
if (e.target.classList.contains("delete")) {
const id = e.target.id;
e.target.parentElement.parentElement.remove(id);
const productToDelete = `https://6060b8b904b05d0017ba2dfb.mockapi.io/products?id=${id}`;
http
.delete(productToDelete)
.then((data) => getProductsAdmin())
.catch("Error on delete!");
}
}
Let me know if you need printscreens or more code. Thanks
I think your parameter's link was wrong, it should be :
https://6060b8b904b05d0017ba2dfb.mockapi.io/products/${id}
the answer above is correct, and finding info about mockapi.io on the internet was hard for me so, I just wanted to answer to the related problems with mockapi.io when deleting a specific object from DB.
When adding new objects to the resource mockapi.io assigns an id to them. And when you want to delete that new object you should make a request(/products/${id}) to that assigned id, but the problem is if you have your own id in the object and mockapi.io assigns another id to this object when adding it to the resource, your request will address different object.
I solved it this way:
First, you change the name of the id that mockapi.io assigns automatically
For example, I changed it to "index"
https://i.stack.imgur.com/N6zY2.png
const { data } = axios.get(`https://UNIQUE_PROJECT.mockapi.io/cart?id=${thisCard.id}`);
await axios.delete(`https://UNIQUE_PROJECT.mockapi.io/cart/${data[0].index}`);
It finds an object with my assigned id, then I make a delete request with index(the id that mockapi.io assigns automatically to new objects).
Important to remember, a delete request(/cart/${id}) works only with identifiers (id, index, etc.) that mockapi.io assigns itself.

Could I get 'creationTime' when I create a new document in Firestore (instead of using 'documentRef.get()' after creation and thus avoid that reading?

Goal: get the creation time of a new Firestore document in the document creation process
First I create a new document with the corresponding data newDocumentData and a field creationTime with the creation time, as shown below:
const newDocumentRef = await collectionRef.add({
...newDocumentData,
creationTime: firebase.firestore.FieldValue.serverTimestamp()
})
Then, I need the creationTime, and I follow like this...
const document = await newDocumentRef.get()
if (document.exists) {
const documentData = document.data()
}
...to finally get my documentData.creationTime.
My question is: Is there any way to get creationTime with newDocumentRef in the first step and, therefore, avoiding the rest of the process?
Thank you!
No, it is not possible with the Client SDKs, "to get the value of creationTime in the first step". FieldValue.serverTimestamp() returns a sentinel value that tells the server to assign a server-generated timestamp in the written data.
In other words the exact value for creationTime will be calculated by the server, and if you want to get this value, you need to query the database for it.
Note that, on the other hand, with the Firestore REST API, when you create a document, you get back (i.e. through the API endpoint response) a Document object that contains, among others, a createTime field.

what does the ids parameter mean on openerp?

I'm using openerp and i need to call a python method from a web module using javascript.
this is the method:
def get_data(self, cr, uid, ids, context=None):
_logger.info('ids es %r',ids);
if context is None:
context = {}
data = {}
data['ids'] = context.get('active_ids', [])
data['model'] = context.get('active_model', 'ir.ui.menu')
data['form'] = self.read(cr, uid, ids, ['user_id', 'date_start', 'date_end'], context=context)[0]
_logger.info('data es %r',data);
_logger.info('data[form] es %r',data['form']);
return data;
however i don't know how to call this method from javascript because i don't really know what the ids parameter should be, anyways this is how i call it (i get an error because i'm not sending the ids parameter)
data = reportModel.call('get_data',[],undefined,{});
so my question is, what is the ids parameter, how does it work and what should i send to this function from javascript in order to succeed?
I am not sure you will be able to call this from javascript at all as you will need to pass in a database cursor from the connection pool for the appropriate database and you may need to use the XMLRPC interface.
That said, these methods exist on an ORM model (or transient model) and the ids parameter is the standard OpenERP pattern of passing in the IDS of records in the model this method is on that you want to process. So if this method is on the account invoice model, the IDS would be a list of ids in the account_invoice table that you want to process.
Note that you just have to have the argument, you don't have to have anything in it or use it. For example, most form on_change methods ignore it as those methods have to cater for users keying new records that don't exist in the database.

Best way of getting the key after $add

I am using angularFire v 0.5.0
On my returned object I do a $add.
What would be the best way to get the generated key?
It must be something in the succes callback of the $add, because the key will come back asynchrounlusly?
scope.settings = $firebase(ref);
scope.settings.value = {
vat: {
inclusive: true
}
}
}
scope.settings.$add (scope.settings.value).then( function ( {
scope.settings.key = ???
});
note: this is not the actual code, this is just to clarify the problem.
The actiual code is inside a factory in the loaded event, and there is a check if there is already a settings object inside the database.
This somewhat strange construct is to make it easyer for consumers of the factory to change the settings. The settings is a singleton. AngularFire does not return a array of objects, but every item is a object in the settings, with its own key.
$add returns a Firebase ref. Call name() on that ref.
scope.settings.$add(…).name();
See https://github.com/firebase/angularFire/blob/master/angularfire.js#L127.
from the angularfire docs:
The $add method takes a single argument of any type. It will append this value as a member of a list (ordered in chronological order). This is the equivalent of calling push(value) on a Firebase reference.
from the firebase docs (about push()):
Returns
A Firebase reference for the generated location.
so, i think the "key" that you want is the return value of the $add.
Maybe they've changed it in newer versions, now it works like this:
$add() will return a promise. You have to use the callback which runs on success. For example:
var something = $scope.somethings.$add({name: "foo"});
something.then(function(e) {
console.log(e.name())
});
This allows you to perform different actions based on the outcome of the save/write attempt to Firebase.

Breeze JS: Is there a way to query entities from data.results?

I have a Breeze web api controller, with methods that accept parameters and do some work, filtering, sorting, etc, on the server.
On the querySucceeded, I'd like to do further querying to data.results. Is there a way to accomplish this? I got this working by exporting/importing data.results to a local manager, and do the projection from there. The projection is needed in order to use the observable collection in a vendor grid control.
var query = datacontext.EntityQuery.from("GetActiveCustomers")
.withParameters({ organizationID: "1" })
.toType("Customer")
.expand("Organization")
.orderBy('name');
var queryProjection = query
.select("customerID, organizationID, name, isActive, organization.name");
return manager.executeQuery(query)
.then(querySucceeded)
.fail(queryFailed);
function querySucceeded(data) {
var exportData = manager.exportEntities(data.results);
var localManager = breeze.EntityManager.importEntities(exportData);
var resultProjection = localManager.executeQueryLocally(queryProjection);
//This is the way I came up with to query data.results (exporting/importing the result entities to a local manager)
//Is there a better way to do this? Querying directly data.results. Example: data.results.where(...).select("customerID, organizationID...)
if (collectionObservable) {
collectionObservable(resultProjection);
}
log('Retrieved Data from remote data source',
data, true);
}
You've taken an interesting approach. Normally a projection returns uncacheable objects, not entities. But you casted this to Customer (with the toType clause) which means you've created PARTIAL Customer entities with missing data.
I must hope you know what you are doing and have no intention of saving changes to these customer entities while they remain partial else calamity may ensue.
Note that when you imported the selected Customers to the "localManager" you did not bring along their related Organization entities. That means an expression such as resultProjection[0].organization will return null. That doesn't seem correct.
I understand that you want to hold on to a subset of the Customer partial entities and that there is no local query that could select that subset from cache because the selection criteria are only fully known on the server.
I think I would handle this need differently.
First, I would bury all of this logic inside the DataContext itself; the purpose of a DataContext is to encapsulate the details of data access so that callers (such as ViewModels) don't have to know internals. The DataContext is an example of the UnitOfWork (UoW) pattern, an abstraction that helps isolate the data access/manipulation concerns from ViewModel concerns.
Then I would store it either in a named array of the DataContext (DC) or of the ViewModel (VM), depending upon whether this subset was of narrow or broad interest in the application.
If only the VM instance cares about this subset, then the DC should return the data.results and let the VM hold them.
I do not understand why you are re-querying a local EntityManager for this set nor for why your local query is ALSO appling a projection ... which would return non-entity data objects to the caller. What is wrong with returning the (partial) Customer entities.
It seems you intend to further filter the subset on the client. Hey ... it's a JavaScript array. You can call stuffArray.filter(filterFunction).
Sure that doesn't give you the Breeze LINQ-like query syntax ... but do you really need that? Why do you need ".select" over that set?
If that REALLY is your need, then I guess I understand why you're dumping the results into a separate EntityManager for local use. In that case, I believe you'll need more code in your query callback method to import the related Organization entities into that local EM so that someCustomer.organization returns a value. The ever-increasing trickiness of this approach makes me uncomfortable but it is your application.
If you continue down this road, I strongly encourage you to encapsulate it either in the DC or in some kind of service class. I wouldn't want my VMs to know about any of these shenanigans.
Best of luck.
Update 3 Oct 2013: Local cache query filtering on unmapped property
After sleeping on it, I have another idea for you that eliminates your need for a second EM in this use case.
You can add an unmapped property to the client-side Customer entity and set that property with a subset marker after querying the "GetActiveCustomers" endpoint on the server; you'd set the marker in the query callback.
Then you can compose a local query that filters on the marker value to ensure you only consider Customer objects from that subset.
Reference the marker value only in local queries. I don't know if a remote query filtering on the marker value will fail or simply ignore that criterion.
You won't need a separate local EntityManager; the Customer entities in your main manager carry the evidence of the server-side filtering. Of course the server will never have to deal with your unmapped property value.
Yes, a breeze local query can target unmapped properties as well as mapped properties.
Here's a small demonstration. Register a custom constructor like this:
function Customer() { /* Custom constructor ... which you register with the metadataStore*/
// Add unmapped 'subset' property to be queried locally.
this.subset = Math.ceil(Math.random() * 3); // simulate values {1..3}
}
Later you query it locally. Here are examples of queries that do and do not reference that property:
// All customers in cache
var x = breeze.EntityQuery.from("Customers").using(manager).executeLocally();
// All customers in cache whose unmapped 'subset' property === 1.
var y = breeze.EntityQuery.from("Customers")
.where("subset", 'eq', 1) // more criteria; knock yourself out
.using(manager).executeLocally();
I trust you'll know how to set the subset property appropriately in your callback to our "GetActiveCustomers" query.
HTH
Once you queried for some data breeze stores those entities on the local memory.
All you have to do is query locally when you need to filter the data some more.
You do this by specifying for the manager to query locally :
manager.executeQueryLocally(query);
Because querying from the database is done asynchronously you have to make sure that you retrieve from the local memory only if there is something there. Follow the promises.

Categories