Cloud Datastore Projection Query with filters with AppEngine NodeJS Standard - node.js

I am learning GCP, and have searched through the documentation. The Projection queries documentation states that they can be used with filters albeit with some limitations. As far as I understand I am not falling within the limitations, but still I cannot make it work.
What I want to do is a simple
SELECT property FROM kind WHERE enabled = TRUE
The properties are marked as indexed, I have also deployed an index.yaml. And my code is the following
const selectQuery = programTypeQuery
.select(entityNameProperty)
.filter('enabled',true);
When commenting the select line, the query works. When commenting the filter line, it also works, but when running both I get the following message in postman.
{
"code": 9,
"metadata": {
"_internal_repr": {}
},
"note": "Exception occurred in retry method that was not classified as transient"
}
My log just shows a 400 status error.
Any help will be appreciated
EDIT:
this is the full code. I have a parameter that indicates the language of the name. in the database I have nameEn and nameEs as properties, so I want to return only the name in the selected language. enabled is a boolean property that indicates if the product is active or not.
const Datastore = require('#google-cloud/datastore');
const datastore = Datastore();
const programTypeQuery = datastore.createQuery('programType')
entityNameProperty = 'name' + req.params.languageCode
const selectQuery = programTypeQuery
.select(entityNameProperty)
.filter('enabled',true);
selectQuery.runQuery()
.then((results) => {
res.json(results);
})
.catch(err => res.status(400).json(err));

From the details you provided it is hard to detect where this issue is being originated. Can you use Google APIs Explorer for Datastore API and try your query. I prepared the request body according to your descriptions, you can click here and execute it by just changing the projectId. By doing this you will receive a sucessful response or an error message with details, it might be easier to detect the root cause from here.

Most likely you are missing a composite index definition. You should be able to look at your GAE logs in stackdriver to see the error message returned from Cloud Datastore.
Since your property name is dynamic you won't be able to use a composite index effectively. You'll probably need to change your data model to something that doesn't use dynamic property names.

Related

How to programatically filter log entries from GCP log?

I have a hard time figuring out how to programatically get specific GCP log entries.
I have multiple Cloud Functions in my project. They all write logs to a log named cloudfunctions.googleapis.com%2Fcloud-functions (maybe it is possible to have separate logs for each cloud function but that is another question I should ask I guess :-)
By using the client library for logging I do the following to retrieve a few log entries, which works fine:
const log = logging.log('cloudfunctions.googleapis.com%2Fcloud-functions');
const [entries] = await log.getEntries({
autoPaginate: false,
pageSize: 5
});
However, I now want to retrieve only entries from one of my cloud functions (function-x) and try to find any details on what to put in the query object for the log.getEntries(query) call. As most GCP users know, finding API information in GCP is sometimes a bit of a hustle... The closest I've gotten regarding the API method above is this page. It list a public resourceNames: string[] property which I try to use, but apparently I do something wrong and need help.
I try e.g.
const [entries] = await log.getEntries({
autoPaginate: false,
pageSize: 5,
resourceNames: ['projects/my-project-id/function-x']
});
But cannot get it to work. I just get an
Error: 3 INVALID_ARGUMENT: Received unexpected value parsing name "projects/my-project-id/logs/cloudfunctions.googleapis.com%2Fcloud-functions/function-x": my-project-id. Expected the form projects/[PROJECT_ID]
So, my question is: How do I do to get log entries from function-x only?
As specified in the page defining resourceNames, the query object also has a filter property but no details on how to use it. A second question is therefore how can this filter property be used? What format does it require? (Once I can retrieve logs from my function I would for example like to filter them on labels and severity).
Finally figured out the response to this (my) question. If I use teh following it works:
const [entries] = await log.getEntries({
autoPaginate: false,
pageSize: 5,
filter: 'resource.labels.function_name=function-x',
resourceNames: ['projects/my-project-id']
});
Turns out, as documented here, resourceNames should be one of
projects/[PROJECT_ID]
organizations/[ORGANIZATION_ID]
billingAccounts/[BILLING_ACCOUNT_ID]
folders/[FOLDER_ID]
and the function name should be placed in the filter instead.

Understanding "x-ms-request-charge" and "x-ms-total-request-charge" in CosmosDB Gremlin API

I am using gremlin (version 3.4.6) package to query my Cosmos DB account targeting Gremlin (Graph) API. The code is fairly straightforward:
const gremlin = require('gremlin');
const authenticator = new gremlin.driver.auth.PlainTextSaslAuthenticator(
`/dbs/<database-name>/colls/<container-name>`,
"<my-account-key>"
);
const client = new gremlin.driver.Client(
"wss://<account-name>.gremlin.cosmosdb.azure.com:443/",
{
authenticator,
traversalsource : "g",
rejectUnauthorized : true,
mimeType : "application/vnd.gremlin-v2.0+json"
}
);
client.submit("g.V()")
.then((result) => {
console.log(result);
})
.catch((error) => {
console.log(error);
});
The code is working perfectly fine and I am getting the result back. The result object has an attributes property which looks something like this:
{
"x-ms-status-code": 200,
"x-ms-request-charge": 0,
"x-ms-total-request-charge": 123.85999999999989,
"x-ms-server-time-ms": 0.0419,
"x-ms-total-server-time-ms": 129.73709999999994,
"x-ms-activity-id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
If you notice, there are two things related to request charge (basically how expensive my query is): x-ms-request-charge and x-ms-total-request-charge.
I have three questions regarding this:
What's the difference between the two?
I noticed that x-ms-request-charge is coming always as 0 and x-ms-total-request-charge as a non-zero value. Why is that? and
Which value should I use to calculate the request charge? My guess is to use x-ms-total-request-charge as it is a non-zero value.
And while we're at it, I would appreciate if someone can tell me the difference between x-ms-server-time-ms and x-ms-total-server-time-ms as well.
These response codes are specific to our Gremlin API and are documented here, Azure Cosmos DB Gremlin server response headers.
For a single request, Gremlin server can send response with multiple partial response messages (loosely equivalent to a page, but returned as a stream instead of multiple request/responses with continuations as is done with SQL API).
x-ms-request-charge is the RUs consumed to resolve a single partial response.
x-ms-total-request-charge is running total RUs consumed up to the current partial response. So when the final message is sent, this will denote the total RUs consumed for the entire request.
Depending on the Gremlin client driver implementation, each partial responses may be exposed to the caller OR the driver will accumulate all responses internally and return a final result. Given the latter, this prompted us to add the x-ms-total-request-charge, so that drivers implemented this way could still resolve the total cost of the request.
Thanks for the question and hope this is helpful.

Srapi - retrieve 1-n property from the Lifecycle call back model parameter

i am using Strapi for a prototype and i am meeting the following issue. I have created a new content type "Checklist" and i added in it a relation property 1 to many with the User model provided by the users-permissions plugin.
Then i wanted to add some custom logic on the lifecycle call back, in beforeSave and in beforeUpdate from which i would like to access the user assigned to the Checklist.
The code looks like that:
{
var self = module.exports = {
// Before saving a value.
// Fired before an `insert` or `update` query.
generateLabel : (model) => {
var label = "";
var day = _moment(model.date,_moment.ISO_8601).year();
var month = _moment(model.date,_moment.ISO_8601).day();
var year = _moment(model.date,_moment.ISO_8601).month();
console.log(model);
if (model.user) {
label = `${model.user}-${year}-${month}-${day}`;
}else{
label = `unassigned-${year}-${month}-${day}`;
}
return label;
I call the method generateLabel from the callback. It works, but my model.user always returned undefined. It is a 1-n property. I can access model.date property (one of the field i have created) without any issue, so i guess the pbs is related to something i have to do to populate the user relation, but i am not sure on how to proceed.
When i log the model object, the console display what i guess is a complete mongoose object but i am not sure where to go from there as if i try to access the property that i see in the console, i will always reach an undefined.
Thanks in advance for your time, i use the following
strapi: 3.0.0-alpha.13.0.1
nodejs: v9.10.1
mongodb: 3.6.3
macos high sierra
Also running into the similar / same issue, I think this has to do with the user permissions plugin, and having to use that to access the User model. Or I thought about trying to find the User that’s associated with the id of the newly created record. I’m trying to use AfterCreate. Anyone that could shed some light on this would be great!
It's because relational attributes are not send in create fonction (See your checklist service add function).
Relations are handled in an other function updateRelations.
The thing you can do is to send values in Checklit.create()

Query Google Cloud Datastore to retrieve matching results

I am using Google Cloud Datastore to save my application data. I have to add a query to get all results matching with Name, Brand or Sku.
Query data with one of the field is returning me records but using all fields together returns me error.
Query:
const term = "My Red";
const q = gstore.createQuery(req.params.orgId, "Variant")
.filter('brand', '=', term)
.filter('sku', '=', term)
.limit(10);
Error:
{"msec":435.96913800016046,"error":"no matching index found.
recommended index is:- kind: Variant properties: -
name: brand - name:
sku","data":{"code":412,"metadata":{"_internal_repr":{}},"isBoom":true,"isServer":true,"data":null,"output":{"statusCode":500,"payload":{"statusCode":500,"error":"Internal
Server Error","message":"An internal server error
occurred"},"headers":{}}}} Debug: internal, error
Also, I want to perform OR operation to get matching results as above will return data with AND operation.
Please help me to find correct path to achieve the desired result.
Thanks in advance and let me know if something is not clear.
The error indicates that the composite index required by the respective query is not in Serving state.
That means it's either not created/deployed or it was recently deployed and is still being built.
Composite indexes must be specifically created and deployed in your app.
If you didn't create it you need to do so. The error message indicates the content the index configuration requires. If you're using the development server it might create it automatically, but you still need to deploy it.
See Indexes docs for more details.
If you recently deployed the composite index please note that it can take some significant amount of time until the matching index is built, depending on how many entities of that kind already exist in the Datastore. You can check the status of the index building in the developer console, on the Indexes page

Adding PartitionKey propery when inserting an entity in Azure table storage for nodejs

This is more of a call for help with an exception when calling insertEntity().
I'm using Nodejs on Azure and editing in Monaco, and I've NPM-installed the latest version of azure storage.
The exception I encounter is: (full stack trace at the bottom)
Unaught exception: Error: Parameter entityDescriptor.PartitionKey for function entityOperation should be an object at ArgumentValidator._.extend.object
I'm basically taking my object to save, and creating 2 new properties: PartitionKey and RowKey. I give them string values. I'm following the examples. I'm not using entityGenerator, as the samples here don't, whereas the examples on the Azure Node developers portal do. I wouldn't mind using entityGenerator on the storage-specific properties if required, but the samples in the node azure github repo seem to suggest that you can use simple strings. The entityGenerator looks a bit ugly and cumbersome, honestly, as you'd have to code extra around the entity when you bring it back.
How can I adjust my code to solve this problem and call insertEntity() with success?
exports.saveTally = function(tally, callback) {
var tableSvc = getAzureTableService();
tableSvc.createTableIfNotExists("tally", function(error, result, response) {
if (!error) {
tally.PartitionKey="tally";
tally.RowKey = tally.id;
tableSvc.insertEntity("tally", tally, function(error, result, response) {
if (error) {
console.log("*Error saving tally " + error.toString());
}
else {
callback(tally.id);
}
});
}
});}
The location of the Azure storage client library has changed to https://github.com/Azure/azure-storage-node. The samples you’re using are from the old location and from an older version of the library which is why they’re not working. You’ll find updated samples and code at the new location.
In the newer version, an Edm type must be specified for each table entity. This is because type is stored in the storage service and we want to make sure that we are storing what you intend. Each table entity is an object with the form {_:value, $:Edm.Type}.
Entity generator is a convenience feature which makes it simpler to construct table entity objects. We return entities in the form just mentioned and using this convenience feature will not change that in any way.

Resources