Multiple endpoints in same query - javascript

It works perfectly, with a single endpoint.
With apollo-link-rest, I have made a client that looks like this
const restLink = new RestLink({ uri: "https://example.com/" })
And export the client with a new ApolloClient({...})
Now to the question
On the same server https://example.com/, there are multiple endpoints, all with same fields but different data in each
The first query that works look like this
export const GET_PRODUCTS = gql`
query firstQuery {
products #rest(type: "data" path: "first/feed") { // the path could be second/feed and it will work with different data
id
title
}
}
`
I want all these different path into one and same json feed, because they all have the same fields, but with different data

Using aliases
You can (should be possible) use standard method to make similar queries - get many data (result) nurmally available as the same shape (node name). This is described here.
{
"1": products(....
"2": products(....
...
}
Paths can be created using variables
Results can be easy combined by iterating over data object. Problem? Only for fixed amount (not many) endpoints as query shouldn't be generated by strings manipulations.
Multiple graphql queries
You can create queries in a loop - parametrized - using Promise.all() and apollo-client client.query(. Results needs to be combined into one, too.
Custom fetch
Using custom fetch you can create a query taking an array of paths. In this case resolver should use Promise.all() on parametrized fetch requests. Combined results can be returned as single node (as required).
Bads
All these methods needs making multiple requests. Problem can be resolved by making server side REST wrapper (docs or blog).

Related

Node.js and express Rest api to create custom fields routes

I am working with node.js and express framework for my rest api server.
I have created get routes with query params and working with them.
But I want to make a functionality like facebook graph api where I can send fields with my api routes such as
/me?fields=address,birthday,email,domains.limit(10){id,name,url}
I am thinking of getting the fields from the query parameters and then splitting them based on , such as
const fields = req.query.fields;
let fieldsArray = fields.split(',');
But how can I pass the sub object attributes and retrieve them from the route like domain field from the above example.
/me?fields=address,birthday,email,domains.limit(10){id,name,url}
If you use a dot-notation like so
/me?fields=address,domains.id,domains.name&dbQueryFilters=domains.limit=10
It could mean:
I want these fields in my response:
address
domains:
id
name
Use these to query the db:
domains:
limit :10
You can add/remove such query variables until it explicitly conveys what your API does while still being very basic. It's always in your best interest to keep things simple and basic.
On the nodeJS side, you can use a library like flat to unflatten the query object:
var fields = flat.unflatten(req.query.fields)
Try sending out the request like:
/me?fields=address,birthday,email,domains.limit%2810%29%7Bid%2Cname%2Curl%7D
There is code for every special character you can get it by doing:
escape("domains.limit(10){id,name,url}") // Returns domains.limit%2810%29%7Bid%2Cname%2Curl%7D
More details: JavaScript escape() Function
Hope this solves your issue.

How to get data from multiple url's in Reactjs?

I want to get json data from multiple url's and display it on frontend.
Following are the url's:
1) localhost:3000/api/getdata1
2) localhost:3000/api/getdata2
3) localhost:3000/api/getdata3
Instead of using .fetch() on each of the url's like below:
.fetch('localhost:3000/api/getdata1')
.fetch('localhost:3000/api/getdata2')
.fetch('localhost:3000/api/getdata3')
Can this be done in more efficent way in ReactJs ?
I was trying:
const dataurls = [
'localhost:3000/api/getdata1',
'localhost:3000/api/getdata2',
'localhost:3000/api/getdata3'
];
const promisedurl = dataurls.map(httpGet);
Promise.all(promisedurls)
.then(data=> {
for (const d of data) {
console.log(d);
}
})
.catch(reason => {
// Receives first rejection among the Promises
});
Please suggest which one should be used or is there any efficient way to do get data from multiple url's.
ReactJS is a View layer library. It has nothing to do with how you aquire any data from server.
Even state libraries, like Redux and Reflux do not implement any method of fetching data. In most cases you do that in your custom app code. Sometimes using extra libraries (e.g. Redux middlewares).
So, yes: your Promise.all(<several https requests here>) is the most natural way to achieve that.

Caching select query data on server side

I am writing an express app, where I'm pushing data from my views to a database. But most of the data is mapped to some other data in database tables.
For example, is a choose student name drop down- once you choose the student by his name , a drop down below - will show all roles that he is allowed for.
So I'm following this pattern of
app.post('\action1', function(req,res){
function querySomething(){
var defered = Q.defer();
connection.query(some_select_query,defered.makeNodeResolver());
return defered.promise;
}
function querySomethingElse(){
var defered = Q.defer();
connection.query(some_other_select_query,defered.makeNodeResolver());
return defered.promise;
}
Q.all([querySomething(), querySomethingElse()]).then((results,err) => {
connection.release()
if(results){
res.render('some_view.ejs', {
result1:results[0][0],
result2:results[1][0]
});
}
else{
res.render('error.ejs',{});
}
})
})
Now the problem is that I have to follow this pattern of selecting something from multiple tables, pass all these function to a promise- and when the results is passed back, goto my view with all those result objects - so that I can use them in my view - as a means of doing drop downs dependent on one another.
Sometimes I have to re-write this multiple times.
Doing a select query like this would be performance intensive especially if all views are using the result of the same query.
Is there any way I can build a cached data store on my express server side code and query that instead of the actual database??
If there is an insert or an update - i will refresh this store and just do a new select * that one time.
What libraries are there on top of express which will help me do this??
Does mysql-cache does the same thing?? I'm also using connection pooling with createPool.
How do I achieve this - or do I just restore to using big mvc's like sails to rewrite my app?
You can try apiCache npm module.
"Sometimes I have to re-write this multiple times."
Based on the business need, you may want to handle each use case separately and this scenario doesn't deal with caching.
Doing a select query like this would be performance intensive especially if all views are using the result of the same query.
This is a classic example for the need of server-side caching.

Breeze Js - Local query of "Lookup Lists"

In application for performance optimization we using bulk entities loading, like in "Lookup Lists" example http://www.breezejs.com/documentation/lookup-lists.
Query looks like this:
entityQuery.from('SomeBreezeAction')
.using(manager)
.execute()
.then(function (res) {
var set1 = res.results[0].first;
var set2 = res.results[0].second;
}
It working very well remotely. Breeze correctly understand entity types of both entities and generate object based on metadata. In same application we using local Breeze queries for Jasmine tests of client side logic. But query like:
entityQuery.from('SomeBreezeAction')
.using(manager)
.executeLocally()
.then(function (res) {
var set1 = res.results[0].first;
var set2 = res.results[0].second;
}
fails with error: Error: Cannot find an entityType for resourceName: 'SomeBreezeAction'. Consider adding an 'EntityQuery.toType' call to your query or calling the MetadataStore.setEntityTypeForResourceName method to register an entityType for this resourceName.
This is reasonable because we are not using toType or setEntityTypeForResourceName in this query. So my question is it possible to use toType or setEntityTypeForResourceName or something else for such queries which returns more than one entity type in one request?
If its important we define metadata manually and have not direct EF or other DB connection.
The problem is that the client has no idea what "SomeBreezeAction" means. The logic for this operation is entirely contained on the server.
What you can do though is create your own function that performs the same queries locally that "SomeBreezeAction" does on the server and combines the results returned into the same 'shape' that your server side query does. This function can then be called whenever you want a local version of the same query.

How to perform sql "LIKE" operation on firebase?

I am using firebase for data storage. The data structure is like this:
products:{
product1:{
name:"chocolate",
}
product2:{
name:"chochocho",
}
}
I want to perform an auto complete operation for this data, and normally i write the query like this:
"select name from PRODUCTS where productname LIKE '%" + keyword + "%'";
So, for my situation, for example, if user types "cho", i need to bring both "chocolate" and "chochocho" as result. I thought about bringing all data under "products" block, and then do the query at the client, but this may need a lot of memory for a big database. So, how can i perform sql LIKE operation?
Thanks
Update: With the release of Cloud Functions for Firebase, there's another elegant way to do this as well by linking Firebase to Algolia via Functions. The tradeoff here is that the Functions/Algolia is pretty much zero maintenance, but probably at increased cost over roll-your-own in Node.
There are no content searches in Firebase at present. Many of the more common search scenarios, such as searching by attribute will be baked into Firebase as the API continues to expand.
In the meantime, it's certainly possible to grow your own. However, searching is a vast topic (think creating a real-time data store vast), greatly underestimated, and a critical feature of your application--not one you want to ad hoc or even depend on someone like Firebase to provide on your behalf. So it's typically simpler to employ a scalable third party tool to handle indexing, searching, tag/pattern matching, fuzzy logic, weighted rankings, et al.
The Firebase blog features a blog post on indexing with ElasticSearch which outlines a straightforward approach to integrating a quick, but extremely powerful, search engine into your Firebase backend.
Essentially, it's done in two steps. Monitor the data and index it:
var Firebase = require('firebase');
var ElasticClient = require('elasticsearchclient')
// initialize our ElasticSearch API
var client = new ElasticClient({ host: 'localhost', port: 9200 });
// listen for changes to Firebase data
var fb = new Firebase('<INSTANCE>.firebaseio.com/widgets');
fb.on('child_added', createOrUpdateIndex);
fb.on('child_changed', createOrUpdateIndex);
fb.on('child_removed', removeIndex);
function createOrUpdateIndex(snap) {
client.index(this.index, this.type, snap.val(), snap.name())
.on('data', function(data) { console.log('indexed ', snap.name()); })
.on('error', function(err) { /* handle errors */ });
}
function removeIndex(snap) {
client.deleteDocument(this.index, this.type, snap.name(), function(error, data) {
if( error ) console.error('failed to delete', snap.name(), error);
else console.log('deleted', snap.name());
});
}
Query the index when you want to do a search:
<script src="elastic.min.js"></script>
<script src="elastic-jquery-client.min.js"></script>
<script>
ejs.client = ejs.jQueryClient('http://localhost:9200');
client.search({
index: 'firebase',
type: 'widget',
body: ejs.Request().query(ejs.MatchQuery('title', 'foo'))
}, function (error, response) {
// handle response
});
</script>
There's an example, and a third party lib to simplify integration, here.
I believe you can do :
admin
.database()
.ref('/vals')
.orderByChild('name')
.startAt('cho')
.endAt("cho\uf8ff")
.once('value')
.then(c => res.send(c.val()));
this will find vals whose name are starting with cho.
source
The elastic search solution basically binds to add set del and offers a get by wich you can accomplish text searches.
It then saves the contents in mongodb.
While I love and reccomand elastic search for the maturity of the project, the same can be done without another server, using only the firebase database.
That's what I mean:
(https://github.com/metaschema/oxyzen)
for the indexing part basically the function:
JSON stringifies a document.
removes all the property names and JSON to leave only the data
(regex).
removes all xml tags (therefore also html) and attributes (remember
old guidance, "data should not be in xml attributes") to leave only
the pure text if xml or html was present.
removes all special chars and substitute with space (regex)
substitutes all instances of multiple spaces with one space (regex)
splits to spaces and cycles:
for each word adds refs to the document in some index structure in
your db tha basically contains childs named with words with childs
named with an escaped version of "ref/inthedatabase/dockey"
then inserts the document as a normal firebase application would do
in the oxyzen implementation, subsequent updates of the document ACTUALLY reads the index and updates it, removing the words that don't match anymore, and adding the new ones.
subsequent searches of words can directly find documents in the words child. multiple words searches are implemented using hits
SQL"LIKE" operation on firebase is possible
let node = await db.ref('yourPath').orderByChild('yourKey').startAt('!').endAt('SUBSTRING\uf8ff').once('value');
This query work for me, it look like the below statement in MySQL
select * from StoreAds where University Like %ps%;
query = database.getReference().child("StoreAds").orderByChild("University").startAt("ps").endAt("\uf8ff");

Categories

Resources