How to Make a ShopifyQL query? - javascript

Shopify recently announced ShopifyQL for easier accessing of analytics data. However, I'm unclear of how to actually make a ShopifyQL call. They do include an example.
{
# "FROM sales SHOW total_sales BY month SINCE -1y UNTIL today" passes a ShopifyQL query to the GraphQL query.
shopifyqlQuery(query: "FROM sales SHOW total_sales BY month SINCE -1y UNTIL today") {
__typename
... on TableResponse {
tableData {
rowData
columns {
# Elements in the columns section describe which column properties you want to return.
name
dataType
displayName
}
}
}
# parseErrors specifies that you want errors returned, if there were any, and which error properties you want to return.
parseErrors {
code
message
range {
start {
line
character
}
end {
line
character
}
}
}
}
}
However, using the GraphiQL tool to run the query hits a number of errors:
{
"errors": [
{
"message": "Field 'shopifyqlQuery' doesn't exist on type 'QueryRoot'",
"locations": [
{
"line": 3,
"column": 3
}
],
"path": [
"query",
"shopifyqlQuery"
],
"extensions": {
"code": "undefinedField",
"typeName": "QueryRoot",
"fieldName": "shopifyqlQuery"
}
}
]
}
I also tried making an authenticated call with the example query above using my app's Node server, but ran into the same issues.
What am I missing here?

Looks like it only works with the unstable version currently:
https://"+shop_name+".myshopify.com/admin/api/unstable/graphql.json
Got a successful response with this.

Is this still working for you?
https://storename.myshopify.com/admin/api/unstable/graphql.json
This was working for past 6 months. but now it getting access denied.
"code": "ACCESS_DENIED",
"documentation": "https://shopify.dev/api/usage/access-scopes",
"requiredAccess": "read_reports access scope, read_customers access scope, read_fulfillments access scope, read_inventory access scope, read_orders access scope, read_products access scope and read_all_orders access scope"
}

Related

Why am I getting an error that my conditions don't match the schema?

I have this query that works:
{
"TableName": "myTable",
"IndexName": "gsi1",
"Limit": 12,
"KeyConditionExpression": "#pk = :pk",
"ExpressionAttributeValues": {
":pk": "TOS"
},
"ExpressionAttributeNames": {
"#pk": "gsi1_pk"
}
}
I attempted to convert it into one using KeyConditions instead of an expression because that makes other things easier. So I changed it to this:
{
"TableName": "myTable",
"IndexName": "gsi1",
"Limit": 12,
"KeyConditions": {
"gsi1_pk": {
"ComparisonOperator": "EQ",
"AttributeValueList": [
{
"S": "TOS"
}
]
}
}
}
I have the GSI configured on my table:
But when I make the request I'm getting this error:
ValidationException: One or more parameter values were invalid: Condition parameter type does not match schema type
I don't understand why I'm getting this error.
My Partition key for this GSI is a string
The only attribute I'm querying against is a string
The name gsi1_pk matches the value I'm querying
Did I miss something in converting this query? I don't understand what I should change to resolve the error because it looks accurate to me.
From this aws doc
This is a legacy parameter. Use KeyConditionExpression instead.
'KeyConditions' >= 'KeyConditionExpression'
Changing your key var in your query should fix this.

How do I query an index properly with Dynamoose

I'm using Dynamoose to simplify my interactions with DynamoDB in a node.js application. I'm trying to write a query using Dynamoose's Model.query function that will search a table using an index, but it seems like Dynamoose is not including all of the info required to process the query and I'm not sure what I'm doing wrong.
Here's what the schema looks like:
const UserSchema = new dynamoose.Schema({
"user_id": {
"hashKey": true,
"type": String
},
"email": {
"type": String,
"index": {
"global": true,
"name": "email-index"
}
},
"first_name": {
"type": String,
"index": {
"global": true,
"name": "first_name-index"
}
},
"last_name": {
"type": String,
"index": {
"global": true,
"name": "last_name-index"
}
}
)
module.exports = dynamoose.model(config.usersTable, UserSchema)
I'd like to be able to search for users by their email address, so I'm writing a query that looks like this:
Users.query("email").contains(query.email)
.using("email-index")
.all()
.exec()
.then( results => {
res.status(200).json(results)
}).catch( err => {
res.status(500).send("Error searching for users: " + err)
})
I have a global secondary index defined for the email field:
When I try to execute this query, I'm getting the following error:
Error searching for users: ValidationException: Either the KeyConditions or KeyConditionExpression parameter must be specified in the request.
Using the Dynamoose debugging output, I can see that the query winds up looking like this:
aws:dynamodb:query:request - {
"FilterExpression": "contains (#a0, :v0)",
"ExpressionAttributeNames": {
"#a0": "email"
},
"ExpressionAttributeValues": {
":v0": {
"S": "mel"
}
},
"TableName": "user_qa",
"IndexName": "email-index"
}
I note that the actual query sent to DynamoDB does not contain KeyConditions or KeyConditionExpression, as the error message indicates. What am I doing wrong that prevents this query from being written correctly such that it executes the query against the global secondary index I've added for this table?
As it turns out, calls like .contains(text) are used as filters, not query parameters. DynamoDB can't figure out if the text in the index contains the text I'm searching for without looking at every single record, which is a scan, not a query. So it doesn't make sense to try to use .contains(text) in this context, even though it's possible to call it in a chain like the one I constructed. What I ultimately needed to do to make this work is turn my call into a table scan with the .contains(text) filter:
Users.scan({ email: { contains: query.email }}).all().exec().then( ... )
I am not familiar with Dynamoose too much but the following code below will do an update on a record using node.JS and DynamoDB. See the key parameter I have below; by the error message you got it seems you are missing this.
To my knowledge, you must specify a key for an UPDATE request. You can checks the AWS DynamoDB docs to confirm.
var params = {
TableName: table,
Key: {
"id": customerID,
},
UpdateExpression: "set customer_name= :s, customer_address= :p, customer_phone= :u, end_date = :u",
ExpressionAttributeValues: {
":s": customer_name,
":p": customer_address,
":u": customer_phone
},
ReturnValues: "UPDATED_NEW"
};
await docClient.update(params).promise();

JSON, node.js: access classes via its name (String)

Here's my situation, I have a JSON that looks somewhat like this:
{
"items": [{
"type": "condition",
"data": {
"type": "comparison",
"value1": {
"source": "MyType1",
"component": "Attribute1"
},
"value2": {
"source": "MyType2",
"component": "Attribute2"
},
"operator": "gt"
}
},
{
"type": "then",
"data": {
"result": "failed",
"message": "value1 is too high"
}
}
]
}
and would want it to translate to:
if (MyType1.Attribute1 > MyType2.Attribute2) {
result = "failed";
console.log("value1 is too high");
}
Now my problem is, I don't know how I would translate the entries of value1 and value2 to actual code, or rather, how I could access the Object MyType1(maybe through something like getAttribute("MyType1")).
Since I am going to have a whole bunch of sources which each have different components, I cant really write a huge dictionary. Or I would like to avoid it.
The goal is to allow creating if - then - statements via some interactive UI, and I figured it'd be best to save that code as .json files. (Think rule management system).
So, TL,DR, How would I access a Class Attribute this.MyType, if I only have a String MyType to go from? And how would I access the value this.MyType.MyValue, if I get another String MyValue?
Thanks in advance.
Edit:
I'd really like to avoid using eval, for obvious reasons. And if I have to - I guess I would need to create Dictionaries for possible JSON Values, to validate the input?
You need some kind of parser. At first we need some way to store variables and maybe flags:
const variables = {};
var in = false;
Then we go through the code and execute it:
for(const command of items){
switch( command.type ){
case "condition":
//...
case "then":
//...
}
}
To access a variable we can simply do
var current = variables[ identifier ];
To store its the other way round:
variables[ identifier ] = current;

How to select a JSON object from Firebase Database?

I have a Firebase structure like below. I want to get the message as a returned object. To do this in SQL like
select messages from HukMesssage
How can I do that?
Can anyone helps me how to change the SQL to Firebase query?
My json file looks like below
{
"HukMessages":
[
{
"To": 1,
"From": 2,
"messages": [
{
"name": "'Venkman'",
"message": "'You on your way?'",
"face": "'img/venkman.jpg'"
},
{
"name": "'Felix He'",
"message": "'Ionic comes with a set of colors to start with, but as a general rule colors are meant to be overridden. '",
"face": "'img/felix.jpg'"
}
]
}
]
}
When you execute a query against the Firebase Database, there will potentially be multiple results. So the snapshot contains a list of those results. Even if there is only a single result, the snapshot will contain a list of one result.
Your code will need to deal with the list. Something like:
var query = firebase.database().ref().child("HukMessages").orderByChild(‌​"From").equalTo('2')‌​;
query.once("value", function(snapshot) {
console.log(snapshot.key); // this will print HukMessages, because that's the location you queried
snapshot.forEach(function(child) {
console.log(child.key); // this will print the key of a message
});
});

Limiting fields returned by mongo dynamically

I use Meteor to query a mongo collection. It has for example the following entry:
{
"_id": "uCfwxKXyZygcWQeiS",
"gameType": "foobar",
"state": "starting",
"hidden": {
"correctAnswer": "secret",
"someOtherStuff": "foobar"
},
"personal": {
"Y73uBhuDq2Bhk4d8W": {
"givenAnswer": "another secret",
},
"hQphob8s92gbEMXbY": {
"givenAnswer": "i have no clue"
}
}
}
What I am trying to do now is:
don't return the values behind "hidden"
from the "personal" embedded document only return the values for the asking user
In code it would look something like this:
Meteor.publish('game', function() {
this.related(function(user) {
var fields = {};
fields.hidden = 0;
fields.personal = 0;
fields['personal.' + this.userId] = 1;
return Games.find({}, {fields: fields});
}, Meteor.users.find(this.userId, {fields: {'profile.gameId': 1}}));
}
Obviously this won't work, because MongoDB won't allow mixed includes and excludes. On the other hand, I cannot switch to "specify only the included fields", because they can vary from gameType to gameType and it would become a large list.
I really hope that you can help me out of this. What can I do to solve the problem?
Typical example of where to use the directly controlled publication features (the this.added/removed/changed methods).
See the second example block a bit down the page at http://docs.meteor.com/api/pubsub.html#Meteor-publish.
With this pattern you get complete control of when and what to publish.

Categories