I need to do query inside logic.js with special character. I have already done the query logic.
My problem occurs when I put special character as one of the parameter.
When I put 'がが', it cannot find the query. When I put its URL encode, I can find the query result. How do I encode my special word in my logic.js so I can query my word?
This is my code
/**
* Track the trade of a commodity from one trader to another
* #param {org.stock.mynetwork.Receive} receive - the receive to be processed
* #transaction
*/
async function receiveCommodity(receive) {
let statement = 'SELECT org.stock.mynetwork.Commodity WHERE (owner == _$owner AND dataType == _$dataType)';
let qry = buildQuery(statement);
//this works
let allAssets = await query(qry, { owner: 'resource:org.stock.mynetwork.Trader#'+'%E3%81%8C%E3%81%8C', dataType: receive.dataType });
//this dont
let allAssets = await query(qry, { owner: 'resource:org.stock.mynetwork.Trader#'+'がが', dataType: receive.dataType });
}
I was searching at the wrong side of SO post, the solution is easy
I just need to encodeURI(yourVariable.toString())
Related
I'm trying to copy one field to another field in the same table with 10,000 + records, in batches of 50 using the Scripting App.
What am I doing wrong in this code block? It only copies the first record. If I remove the await, it'll copy 15 records then stop.
let table = base.getTable('Merchants');
let view = table.getView('Grid view');
let query = await view.selectRecordsAsync();
let records = query.records;
updateLotsOfRecords(records);
async function updateLotsOfRecords(records) {
let i = 0;
while (i < records.length) {
const recordBatch = records.slice(i, i + 50);
for (let record of recordBatch) {
let sourceValue = record.getCellValue('Merchant');
await table.updateRecordAsync(record, { 'LogoBase64': sourceValue });
}
i += 50;
}
}
you should use updateRecordsAsync function, not updateRecordAsync
When using single update function in loop, there is no sense to divide it into batches.
You exceed some limit of calls per second, that's why it stops.
For multiple updates, you need to use updateRecordsAsync, like this
while (recordsToWrite.length > 0) {
await updates.updateRecordsAsync(recordsToWrite.slice(0, 50));
recordsToWrite = recordsToWrite.slice(50);
}
Data that you should pass to it, more complex. I learned JS for 3 months and still have difficulties understandins all these "arrays of arrays of objects, passed via object's property". But that's the key to unerstand JS.
It's quite hard to leave basic/pascal habits, with plenty of inserted FOR loops, and GOTO sometimes))
I think, you already found the answer for 2 months, so my answer may be useless, but when i write it here, maybe i understand it better for myself. And help to some beginners also.
For single write, you pass (record, Object), where object is {field:'Value}
For multiple, you should pass
Array of Objects, where
Object is {id:recordID, fields:{object2}} , where
object2 is array of obj3 [ {obj3},{obj3}, {obj3} ], where
obj3 is a { 'Name or ID of field': fieldvalue }
you script might be:
let query = await view.selectRecordsAsync();
let updates=query.records.map(rec=>{
Map method can be applied for arrays, and 'query.records' is array of records. Here
'rec' is loop variable inside this "arrowfunction"
now let's create obj3 , in our case { 'Name or ID of field': fieldvalue }
{'LogoBase64':rec.getCellValue('Merchant')}
wrap it into fields property
fields:{'LogoBase64':rec.getCellValue('Merchant')}
and add record id
wrapping as Object.
To avoid complex string with linebreaks, and to make object creation easier, we can do it with function:
{rec.id, fields:{'LogoBase64':rec.getCellValue('Merchant')}}
fuction myObj(rec){return {rec.id, fields:{'LogoBase64':rec.getCellValue('Merchant')}}
map(rec=>myObj(rec)) - can be written as map(myObj)
we need array of objects, and map method gets first array, doing something with each element and return other array, of results. like we need.
and now finally we get
let table = base.getTable('Merchants');
let view = table.getView('Grid view');
let query = await view.selectRecordsAsync();
function myObj(rec){return {'id':rec.id,'fields':{'Logobase64':rec.getCellValue('Merchant')}}};
let updates=query.records.map(myObj);
while (updates.length > 0) {
await table.updateRecordsAsync(updates.slice(0, 50));
updates = updates.slice(50); }
According to the documentation, it needs to follows the Form Post rules at: https://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13.4. When looking at that information it did not give me much to work with in terms of complex objects or maps.
Right now, If I have a list for example: Each item in the list needs to be stringified.
var params = {"list": [1,2,3]};
// needs to be stringed.
params["list"] = params["list"].map((item)=>item.toString()).toList();
Simple. Also all base items need to be a string as well
var params = {"number": 1, "boolean": true};
params = params.forEach((k,v)=> params[k].toString());
But how do we handle maps?
var params = {"map": {"a":1,"b":"foo","c":false,"d":[]}};
// ??
It seems that after testing in my app and in dart pad, you need to make sure everything is strings, so i am trying to come up with a way to effectively cover lists, maps, and maybe more complex objects for encoding.
var params = {};
params["list"] = [1,2,3];
params["number"] = 1;
params["boolean"] = true;
params["map"] = {"a":1,"b":"foo","c":false,"d":[]};
params.forEach((String key, dynamic value){
if(value is List){
params[key] = value.map((v)=>v.toString()).toList();
}else if(value is Map){
// ????
}else{
params[key] = value.toString();
}
//maybe have an additional one for custom classes, but if they are being passed around they should already have their own JSON Parsing implementations.
}
Ideally, the result of this would be passed into:
Uri myUri = new Uri(queryParameters: params);
and right now, while i solved the list issue, it doesn't like receiving maps. Part of me just wanted to stringify the map as a whole, but i wasn't not sure if there was a better way. I know that when someone accidentally stringified the array, it was not giving me: ?id=1&id=2 but instead ?id=%5B1%2C2%5D which was not correct.
I don't think there is any special support for maps. Query parameters itself is a map from string to string or string to list-of-strings.
Everything else need to be brought into this format first before you can pass it as query parameter.
A simple approach would be to JSON encode the map and pass the resulting string as a single query parameter.
I have a HTTP GET request that returns either:
{"events":"Event Goes Here"}
or
{"service":"Service goes here"}
At the moment I'm writing two HTTP Get functions so that when I get to:
if let results: NSArray = jsonResult["services"] as? NSArray {
or
if let results: NSArray = jsonResult["events"] as? NSArray {
I know that Im getting the services or the events Json data.
I want to be able to streamline the HTTP Get request so that I can call in a single function:
func makeGETRequest(urlRequest: String) {
how do I read the string in json0 to be able to determine if its an event or a service?
You seem to already know how to parse the data, but are asking how you might wrap it up to avoid redundancy.
I think you are looking for something like this:
func getStuff(urlRequest:String) -> Result
where Result is an enum with associated values for your payload. Documentation can be found here
You could then call the function something like this:
switch (getStuff("someUrl")) {
case let .Events(events):
doStuffWith(events)
break
case let .Service(serviceStuff):
doStuffWith(serviceStuff)
break
}
The baseline for the form you suggest though, is that if you want to use a common function, you have to return a multiplexed type. Your other option, is for it to call type specific handler functions / closures for each of the possible types, so you are not relying on the return type, but are reacting to the results with further calls such that all processing is done by the time that your getStuff() function returns.
As far as actual parsing goes, you would just use a series of if-let unwrappings to check for which result you got.
I don't do Swift, so translate the following ObjC to Swift and it may work, this is just a snippet, but this won't work because json[#"XXX"] requires an NSDitionary
- (id)initWithJson:(NSArray *)json
{
NSArray* object = json[#"events"] ?: json[#"service"];
self = [super initWithJson:object];
if (self == nil)
{
return nil;
}
//do work
return self;
}
so, you should try to reform your JSON packet that you get from the server, I can't image it being set up in a way that it doesn't send you a dictionary first that you must then parse to an array.
or something like this:
NSString * valueYouWant = json[#"events"] ?: json[#"service"];
using this:
-(NSString*)getValue:(NSDictionary*)json
{
NSString * valueYouWant = json[#"events"] ?: json[#"service"];
return valueYouWant;
}
you would call this by doing sending your "response object" from the server to the NSString method above
I am curious as to what is the major significance, if any in regards to taking a unit or not in code similar to below. What are the advantages or disadvantages. To my current understanding, taking a unit will implement a function that returns a value while not taking one just simply represents the value. Looking for some clarity here.
code without Unit:
let consumerKey =
// retrieve keys
query{
for row in db.Keys do
select {
consumerKey = row.ConsumerKey;
consumerSecret = row.ConsumerSecret
}
exactlyOneOrDefault
}
code with Unit:
let consumerKey() =
// retrieve keys
query{
for row in db.Keys do
select {
consumerKey = row.ConsumerKey;
consumerSecret = row.ConsumerSecret
}
exactlyOneOrDefault
}
The first block of code binds a value of type query<_> to identifier consumerKey while the second binds a value of type () -> query<_> to identifier consumerKey. The second is a function which when given unit will return a value of type query<_>.
In this example, the difference between the two are explicitly captured by their signatures. In other words, the first can be obtained from the second by invoking the function value with (). In terms of runtime, the second will always return a new underlying object instance, while the first one is fixed.
In cases where the evaluation causes side effects, the same would not hold. For example in thw following:
let value1 = Guid.NewGuid()
let value2 () = Guid.NewGuid()
A value1 cannot be obtained via value2 because a different value would be returned for each invocation.
I want fetch the details of a Collection in Odata services like the following URL
http://my.company.com/odata/Employee('1234')/Details
I tried with the following code to do so. Not sure whether fromEntityKey is the right thing to do or anything else.
manager = new breeze.EntityManager(collectionData.serviceName);
var empType = manager.metadataStore.getEntityType("Employees");
var entityKey = new EntityKey(empType, '1234');
var query = EntityQuery.fromEntityKey(entityKey);
But it gives me an error "Be sure to execute a query or call fetchMetadata first."
I also tried that from this link. But I'm still getting the same.
Can any one help me on this?
You can't use manager.metadataSote.getEntityType("Employees") until metadata has been retrieved from the server. By default this occurs during the first query operation, but your code is attempting to use the metadata before it has been retrieved.
Also, I think that you are confusing the name of your resource "Employees" with the type of the instances returned by your resource, probably "Employee". I would also check whether your key's datatype is numeric or a string. The example below assume its numeric (unlike your example where the datatype of the key is presumably a string because you are quoting it).
So you have two approaches, either force the metadata to be fetched before you compose your query, like this:
manager = new breeze.EntityManager(serviceName);
manager.fetchMetadata().then(function () {
var empType = manager.metadataStore.getEntityType("Employee");
var entityKey = new EntityKey(empType, 1);
var query = EntityQuery.fromEntityKey(entityKey);
// if you want to also see the queries details
query = query.expand("Details");
return manager.executeQuery(query);
}).then(function (data) {
var results = data.results;
ok(results.length === 1, "should have returned a single record");
var emp = results[0];
));
or if you know the string name of the 'key' ("Id" in the example below) field, use it directly
manager = new breeze.EntityManager(serviceName);
var query = EntityQuery.from("Employees")
.where("Id", "==", 1)
.expand("Details");
manager.executeQuery(query).then(function(data) {
var results = data.results;
var emp = results[0];
});