Airtable add column dynamically - node.js

I have a base in airtable and now I need to up columns(fields) programmatically.
For example sql has a query for this operation
ALTER TABLE Employees
ADD EmployeeID numeric NOT NULL IDENTITY (1, 1)
Is there a API for Airtable to do such operations?

Airtable offers an API to use, but not for adding columns. There is a Node.js package and several other programing libraries available on Github.
They have official Doc's as well https://airtable.com/api. With out getting creative and hacking something together, it is not possible to modify a table’s schema via the API. So you cannot do actions like add columns or modify the values in an existing table.
var Airtable = require('airtable');
var base = new Airtable({apiKey: 'YOUR_API_KEY'}).base('app$$%&#*(#');
base('Employees').update('EmployeeID', {
"EmployeeID": "Number"
}, function(err, record) {
if (err) { console.error(err); return; }
console.log(record.get('EmployeeID'));
});
Here is a quick snippet of an update function to update a record.

you can't update dynamically an Airtable table. You can update only the existent field values. The response from Nick C is the syntax to PATCH a record.

Related

Airtable sometimes return results and sometimes not

I am using Node.js library to communicate with AirTable, official js library. I am having a problem with filterByFormula. Sometimes when I try to find record from AirTable I don’t get results even though I am pretty sure that there should be some results. My logic is such that if I do not find the record in AirTable I create a new one. If I find it I will update the existing one. This logic leads to problem with same entries entered twice.
This is my query:
getReservationByID: async (externalID) {
let reservations = await calendarBase('Reservations').select({
view: 'Main View',
filterByFormula: `{External ID} = \"${externalID}\"`,
maxRecords: 1,
}).all();
return (reservations.length > 0) ? reservations[0] : null;
},
And this function is used like this:
let oldReservation = await getReservationByID(reservation.id);
if (!oldReservation) {
createNewReservation(reservation);
} else {
updateReservation(reservation);
}
As you can see, it is essential for me to get record from AirTable if it exists, but sometimes AirTable is not returning an existing record with given ID and then I get duplicate with same external ID. Am I doing something wrong or is there some issue that I am not aware of?
I have managed to solve the problem. I have removed the view from query and now everything is working. If no view is included, Airtable will search all records in the table which match your formula. If you specify the view, Airtable will limit its search to just that view and then find all records that match your formula. If you have a filter on the view that you put in select, in my case 'Main View', then you may be hiding certain records from your script.
My new query looks like this:
getReservationByID: async (externalID) {
const reservations = await calendarBase('Reservations').select({
filterByFormula: `{External ID} = \"${externalID}\"`,
maxRecords: 1,
}).all();
return (reservations.length > 0) ? reservations[0] : null;
},

In Cloud function how can i join from another collection to get data?

I am using Cloud Function to send a notification to mobile device. I have two collection in Firestore clientDetail and clientPersonalDetail. I have clientID same in both of the collection but the date is stored in clientDetail and name is stored in clientPersonal.
Take a look:
ClientDetail -- startDate
-- clientID
.......
ClientPersonalDetail -- name
-- clientID
.........
Here is My full Code:
exports.sendDailyNotifications = functions.https.onRequest( (request, response) => {
var getApplicants = getApplicantList();
console.log('getApplicants', getApplicants);
cors(request, response, () => {
admin
.firestore()
.collection("clientDetails")
//.where("clientID", "==", "wOqkjYYz3t7qQzHJ1kgu")
.get()
.then(querySnapshot => {
const promises = [];
querySnapshot.forEach(doc => {
let clientObject = {};
clientObject.clientID = doc.data().clientID;
clientObject.monthlyInstallment = doc.data().monthlyInstallment;
promises.push(clientObject);
});
return Promise.all(promises);
}) //below code for notification
.then(results => {
response.send(results);
results.forEach(user => {
//sendNotification(user);
});
return "";
})
.catch(error => {
console.log(error);
response.status(500).send(error);
});
});
}
);
Above function is showing an object like this
{clienId:xxxxxxxxx, startDate:23/1/2019}
But I need ClientID not name to show in notification so I'll have to join to clientPersonal collection in order to get name using clientID.
What should do ?
How can I create another function which solely return name by passing clientID as argument, and waits until it returns the name .
Can Anybody please Help.?
But I need ClientID not name to show in notification so I'll have to join to clientPersonal collection in order to get name using clientID. What should do ?
Unfortunately, there is no JOIN clause in Firestore. Queries in Firestore are shallow. This means that they only get items from the collection that the query is run against. There is no way to get documents from two top-level collection in a single query. Firestore doesn't support queries across different collections in one go. A single query may only use properties of documents in a single collection.
How can I create another function which solely return name by passing clientID as argument, and waits until it returns the name.
So the most simple solution I can think of is to first query the database to get the clientID. Once you have this id, make another database call (inside the callback), so you can get the corresponding name.
Another solution would be to add the name of the user as a new property under ClientDetail so you can query the database only once. This practice is called denormalization and is a common practice when it comes to Firebase. If you are new to NoQSL databases, I recommend you see this video, Denormalization is normal with the Firebase Database for a better understanding. It is for Firebase realtime database but same rules apply to Cloud Firestore.
Also, when you are duplicating data, there is one thing that need to keep in mind. In the same way you are adding data, you need to maintain it. With other words, if you want to update/detele an item, you need to do it in every place that it exists.
The "easier" solution would probably be the duplication of data. This is quite common in NoSQL world.
More precisely you would add in your documents in the ClientDetail collection the value of the client name.
You can use two extra functions in this occasion to have your code clear. One function that will read all the documents form the collection ClientDetail and instead of getting all the fields, will get only the ClientID. Then call the other function, that will be scanning all the documents in collection ClientPersonalDetail and retrieve only the part with the ClientID. Compare if those two match and then do any operations there if they do so.
You can refer to Get started with Cloud Firestore documentation on how to create, add and load documents from Firestore.
Your package,json should look something like this:
{
"name": "sample-http",
"version": "0.0.1",
"dependencies": {
"firebase-admin": "^6.5.1"
}
}
I have did a little bit of coding myself and here is my example code in GitHub. By deploying this Function, will scan all the documents form one Collection and compare the ClientID from the documents in the other collection. When it will find a match it will log a message otherwise it will log a message of not matching IDs. You can use the idea of how this function operates and use it in your code.

Loopback query which compares field values

Say i have the following Scheme
Product: {
Quantity: Number,
SelledQuantity: Number
}
Would it be possible to write a query where all the results returned are where Quantity=SelledQuantity?
If so, is there a way to use it when doing a populate? (Perhaps inside the match field in the opts object ?)
I use mysql connector.
yes as I understood your problem you can do this by following rest call.
http://localhost:3000/api/products?filter[where][SelledQuantity]=n
this will give you the desired results.
This question is more related to MySQL query. But you can achieve it by javascript as follows:
Product.find({}, fuction(err, products) {
if(err) throw err;
//considering products as array of product. Otherwise you can get to depth for array of product.
var filteredProducts = products.filter(function(p1) {
return p1.Quantity === p1.SelledQuantity;
});
//Your desired output
console.log(filteredProducts);
});
This will be slow but will work for smaller database size. For more optimized answer, ask the question in mysql section with respect to database and table structure.

insert custom value to table using grocerycrud Add/Edit

I have a table customer with fields id,name,nickname.. I'm using grocery crud for add/edit. The field nickname should be automatically created based upon the name field. Can anyone suggest what can be done to accomplish this
You can accomplish this by using the callback_before_insert function of grocerycrud.
Here is a link to the description: callback_before_insert
Before you render your output add this:
$crud->callback_before_insert(array($this,'create_nickname_callback'));
Add the callback method:
function create_nickname_callback($post_array) {
$post_array['nickname'] = your_nickname_value;
return $post_array;
}

Sails.js: Dynamic table name on models

I have made a JS logger application in Sails.js and everything looks great.
Now, I'm on my way to scale the application: I need to use several tables for the same model (e.g. a table for session1 sesson2 etc based on id).
Let's say that for model "Pageview", I'll be using different tables, like "Pageview1", "Pageview2", and so on.
How could I define dynamically the tableName of that model, so I can change it on every request according to a param or attribute.
So far, I have tried this way
var tableId = 2;
Pageview.tableName = "pageview" + tableId;
Pageview.create(values, function...);
That code does not break the application, or throw any errors, but the record was saved on the default table, instead of the one I wanted.
I dont think it is possible to do so , but when i read this
I think you can use the custom format to dynamically define table names.
If you are inserting a row into a table with an auto increment primary key, you can retrieve the insert id like this:
connection.query('INSERT INTO posts SET ?', {title: 'test'}, function(err, result) {
if (err) throw err;
console.log(result.insertId);
});
if this is valid for rows , then it might be valid for tables.

Resources