In Tableau's graphiql, how to I filter for populated elements? - tableau-api

Using the borwser, I want to get back the names of workbooks that have upstream Flows. I think s something like below:
query fq {
workbooks(filter: {has: upstreamFlows})
{
name
upstreamFlows {
name
}
}
}
That gives me error Validation error of type WrongType: argument 'filter' with value 'ObjectValue{objectFields=[ObjectField{name='has', value=EnumValue{name='upstreamFlows'}}]}' contains a field not in 'Workbook_Filter': 'has' # 'workbooks'",
Looking for how to do it in the browser, am familiar with how to do it using api
Does Tableau's graphiql allow for filtering on missing/not missing ?

Related

Netsuite - REST API - Making query with Token Based Authentication (TBA) - (in Python)

This is a follow up to the successful call using Netsuite Token Based Authentication (TBA) REST webservice,
I would like to get some guidance on how to perform a query.
I am supposed to read records like this (please see screenshot)
how can I perform a specifc query (by table for a list of records and also specific record) ?
https://gist.github.com/axilaris/4386c3537d04737d3775c156562b7545 <-- here is the python code for the TBA that has worked successful. I would like to know how to construct the next step on how to perform the query and read specific record (as shown in the screenshot).
This is a custom record with an ID like this customrecord1589
To query a specific record: You're going to need to create/ deploy a RESTlet in Netsuite similar to the following:
/**
* #NApiVersion 2.1
* #NScriptType Restlet
*/
define([
"N/log",
"N/search",
], function (log, search) {
function post(context) {
return JSON.stringify(getCustomRecords(context));
}
function getCustomRecords(context) {
log.debug('POST Context', context);
return search.lookupFields({
//Change CUSTOM_RECORD to the type of custom record you are querying
type: search.Type.CUSTOM_RECORD + '1589',
id: context.id,
columns: context.fields,
});
}
return {
post: post,
};
});
In your Python Script: Make sure you change the URL of the request to the deployment URL of this new RESTlet. Also, make sure to pass any parameters you need (like 'id' or 'fields' in my example) in your POST request payload. So instead of:
payload = {
"name":"value",
"foo":"bar",
"duck":"hunt",
}
pass
payload = {
"id":"9999999",
"fields": ["custrecord_field1", "custrecord_field2"],
}
where id is the internalid of the record you want to query and the fields array are the internalids of the fields you want values from.
If this goes successfully, the result should show up as conn.text in your python script!

Strapi - How to GET data sorted based on relation property?

I have an Articles table and it has a relation with the Authors table. Each author has a name property. I want to make a GET request for the articles and receive the articles sorted based on their author's name.
When I use _sort=author in the url parameters, I get the articles sorted based on the author object's ID.
When I use _sort=author.name in the url parameters, I get the articles in a seemingly random order but definitely not based on author.name.
How can I get the data sorted based on author.name?
I use mongoDB as my database.
That is the default behavior of _sort. However, you can simply accomplish this by overriding the find method in api/article/services/article.js to sort by Author's name like so:
module.exports = {
async find(params, populate) {
let result = await strapi.query('article').find(params, populate);
if (params._sort == 'author')
return result.sort((a, b) => (a.author.name > b.author.name) ? 1 : -1);
return result;
},
}
Check the documentation for customizing services to get more info: https://strapi.io/documentation/v3.x/concepts/services.html#concept

get route only with specified parameter

I am new to MongoDB and CRUD APIs.
I have created my first database and inserted some data. I can do get, post and delete requests.
Now I want to request a 'get' by adding a parameter, so I do the following:
router.get('/:story_name', async function (req, res, next) {
const selectedStory = await loadStoryToRead()
res.send(await selectedStory.find({}).toArray())
})
say that story_name is S1C1,
I can do http://localhost:3000/api/whatever/s1c1 to get the data.
I would have expected to retrieve the data ONLY by using the specified parameter, however I can use the ID or the date or any other parameter found in the json file to get the data.
for example I can do
http://localhost:3000/api/whatever/5d692b6b21d5fdac2... // the ID
or
http://localhost:3000/api/whatever/2019-08-30T13:58:03.035Z ... // the created_at date
and obtain the same result.
Why is that?
How can I make sure that if I use router.get('/:story_name' ... I can retrieve the data only if I use the 'story_name' parameter?
Thanks!
* UPDATE *
my loadStoryToRead() looks like this:
async function loadStoryToRead () {
const client = await mongodb.MongoClient.connect(
'mongodb+srv://...', {
useNewUrlParser: true
})
return client.db('read').collection('selectedStory')
}
I will try to reformulate my question.
I want to ensure that the data is retrieved only by adding the 'story_name' parameter in the URL and not by adding any other parameter within the file.
The reading that I have done suggested to add the parameter to the get request, but when I do it, it doesn't matter what parameter I enter, I can still retrieve the data.
The delete request, however, is very specific. If I use router.delete('/:id'... the only way to delete the file is by using the ID parameter.
I would like to obtain the same with a get request and not using the 'id' but by using 'story_name'.
you can use regular expression capabilities for pattern matching strings in queries.
Syntax is:
db.<collection>.find({<fieldName>: /<string>/})
for example, you can use
var re = new RegExp(req.params.story_name,"g");
db.users.find({$or:[{"name": re}, {"_id": re}, {..other fields}]});
You can use $and and $or according to your requirement.
To read more follow the link
https://docs.mongodb.com/manual/reference/operator/query/regex/

graphql - Combining results from multiple resolvers into one

I have a set of functions at the server side which each return a list of objects of the same type based on the passed parameters to the resolvers in the GraphQL query-
query {
objListQuery {
objResolver1(params) {
obj-id
}
objResolver2(different params) {
obj-id
}
...
}
}
Here, objResolver1 and objResolver2 send back a list of obj objects.
Server side -
function objResolver1(params) -> returns list of obj
function objResolver2(different params) -> returns list of obj
...
I want to perform a logical AND between the results of the resolvers that is, find out the common objects in the results of the different resolvers.
Instead of getting the individual lists, I only want the combined list.
One way is to aggregate the results at the client side but this will increase the amount of duplicated data sent by the server.
What is the best way to achieve this at the server side? What changes are required in the schema?
--------------------EDIT--------------------
The data source is a JSON array of obj objects which is obtained from an external service at the server. Data source is not a database.
Parameters in each resolver can be one or many. It is used for filtering the objects. For example, the data store will have the structure as:
[
{"dateCreated":"2011-08-12T20:17:46.384Z",
"type":"customer",
....
},
{"dateCreated":"2011-08-14T20:17:46.384Z",
"type":"test",
....
}
]
resolvers will be of the form:
dateResolver(String startDate, String endDate) -> returns list of obj whose dateCreated is within the range
typeResolver(String[] type) -> returns list of obj whose type is anyone of the values passed in the array.
Assumed you're using a database you're somehow asking how to shift constraints from database- or repository-layer on controller-level.
While this has some weakness on model-level perhaps, it might depend on the class-implementation if you can easily change the objResolver in the kind that you just build one that allows more parameters like this:
query {
objListQuery {
objResolver(params1, params2, constraint) {
...
}
}
}
Like this you could create a database-query that is directly fetching the right result or you can perform several queries and resolve them inside the objResolver. If the constraint is always AND you could leave the parameter away, but perhaps you like to offer the possibility to use also OR, XOR, or others.
If the amount of parameter-sets is always 2, then it's simple like my code above, also considering the optional constraint. If the amount of parameter-sets might be variable, i.e. 4 or 5, then it's getting complicated if you still want to offer the constraint-parameter(s). Without constraint-parameter(s) it's simple, you just could note the function without parameters but check for the amount of parameters in the caller and handle them accordingly, in the caller you just use so many parameters as required.
query {
objListQuery {
objResolver() {
paramArray = getArguments();
}
}
}
Like written above it's getting hard, if you still want to offer constraint-parameters here, but I'd suggest that would be material for another question.
You can implement a Connection interface, with a single resolver to allow a one-step querying mechanism. You can reduce query endpoints using this technique.
E.g, an example query would look like:
allObjects(start: "01-01-2019", end: "04-29-2019", types:["test", "sales"]){
nodes {
id,
dateCreated,
type
}
}
In the resolver, you can use this criteria to prepare and return the data.
Benefits:
Less query endpoints.
Filtering and pagination.
Your filter interface can be quite fancy:
allObjects(
dateCreated: {
between:{
start,
end
},
skipWeekends: true
},
types: {
include:[],
exclude: []
}
)
Add new criteria as your needs grow. Start with what you want and take it from there.

How to concat two columns for search with feathers-sequelize?

I need to search for users by name, their first name and last names are stored in separate columns in a postgresql database. The columns need to be concatenated for search to work properly. Typing the full first and last name of a user should match a result.
What could I pass as a query to the find method of a Feathers service that would allow me to do this?
As in the answer linked you can pass the where clause to the Feathers service by modifying params.query in a before hook:
app.service('users').before({
find(hook) {
const where = Sequelize.where(Sequelize.fn("concat",
Sequelize.col("firstname"),
Sequelize.col("lastname")), {
like: '%John Do%'
}
);
hook.params.query.where = where;
}
})