Save the date! Join us on October 16 for our Product Ops launch event. Register here.
Oct 21, 2020 06:04 AM
Hi Airtable script gurus! I need help.
I am working off of a code that searches for key words and returns results. The code works when var “districtRecord” is an input. However, I need to run the code on 10k+ records, so using the input would take forever selecting one at a time. I attempted to update the code to run through all the records in the table, and broke it. I keep getting an error saying there is a missing “)” on line 1.
"SyntaxError: missing ) after argument list
on line 1
at l on line 1
at Generator._invoke on line 1
at Generator.forEach.e. [as next] on line 1
at e on line 1
at s on line 1
on line 1
on line 1
"
Here is the entire code:
let districtTable = base.getTable(“Districts”);
let districtRecord = await districtTable.selectRecordsAsync();
let searchQuery = districtRecord.getCellValueAsString(“Keywords”);
let resultsField = districtTable.getField(“Results”);
//this is the attempt to run through all records:
for (let record of districtRecord.records){
async function searchAsync(searchTerm) {
let response = await fetch(
https://api.apify.com/v2/actor-tasks/EFvVjhi1CSuOfd09L/run-sync-get-dataset-items?token=SsEpDxFwqJ7FgXL2TpN3EmicG
;
{
method: “POST”,
headers: {“content-type”: “application/json”};
body: JSON.stringify({queries: searchTerm});
};
);
let result = await response.json();
let resultLines = ;
for (let {searchQuery, organicResults} of result) {
resultLines.push(## ${searchQuery.term}
);
for (let {title, url, description} of organicResults) {
resultLines.push(- [**${title}**:](${url}) ${description}
);
}
}
return resultLines.join(’\n’);
}
if (searchQuery) {
let results = await searchAsync(searchQuery.split(’,’).map(term => term.trim()).join(’\n’));
await districtTable.updateRecordAsync(record, {[resultsField.id]: results});
}
}
Thanks for any assistance!!
(Side Note: once I get this to work - I really need to figure out how to replace the apify web searching with a URL ON the record. Essentially, for each record, go to the URL column URL, search for the Keyword(s) from the “Keywords” column and return the results of that search to the results column on that record. Is that possible?)
Solved! Go to Solution.
Oct 26, 2020 07:17 AM
Hi Jeremy,
Thanks for the tip! Your assumptions are correct. I would like it to run through each record, using the search term within that record.
I got the code to work, running through one record at a time. Thanks!
let districtTable = base.getTable("Districts(Education Agencies)");
let districtsQuery = await districtTable.selectRecordsAsync();
let record = districtsQuery.records[0].id;
let resultsField = districtTable.getField("SearchResults");
output.text ("Searching....")
for (let record of districtsQuery.records){
let searchQuery = record.getCellValueAsString("Keywords");
if (searchQuery) {
let results = await searchAsync(searchQuery.split(',').map(term => term.trim()).join('\n'));
async function searchAsync(searchTerm) {
let response = await fetch(
`https://api.apify.com/v2/actor-tasks/EFvVjhi1CSuOfd09L/run-sync-get-dataset-items?token=SsEpDxFwqJ7FgXL2TpN3EmicG`,
{
method: "POST",
headers: {"content-type": "application/json"},
body: JSON.stringify({queries: searchTerm}),
}
);
let result = await response.json();
let resultLines = [];
for ( let {searchQuery, organicResults} of result) {
resultLines.push(`## ${searchQuery.term}`);
for ( let {title, url, description} of organicResults) {
resultLines.push(`- [**${title}**:](${url}) ${description}`);
}
}
return resultLines.join('\n');
}
await districtTable.updateRecordAsync(record, {SearchResults: results})
}
}
output.text ("search complete.")
Oct 21, 2020 07:36 AM
One thing I notice right away is that inside your fetch()
method, you have a semi-colon after the URL and before the body. That should be a comma, because it is separating arguments to the fetch()
method. There is also no need for the semi-colon after the body.
Oct 21, 2020 07:58 AM
@Jeremy_Oglesby
Thanks, I have corrected that. I no longer get an error message, it completes the RUN, but still doesn’t work (all the results field cells are still empty).
Here is the updated code:
let districtTable = base.getTable(“Districts(Education Agencies)”);
let districtRecord = await districtTable.selectRecordsAsync();
let record = districtRecord.records[0]
let searchQuery = record.getCellValueAsString(“Keywords”);
let resultsField = districtTable.getField(“Results”);
for (let record of districtRecord.records){
async function searchAsync(searchTerm) {
let response = await fetch(
https://api.apify.com/v2/actor-tasks/EFvVjhi1CSuOfd09L/run-sync-get-dataset-items?token=SsEpDxFwqJ7FgXL2TpN3EmicG
,
{
method: “POST”,
headers: {“content-type”: “application/json”},
body: JSON.stringify({queries: searchTerm}),
}
);
let result = await response.json();
let resultLines = ;
for (let {searchQuery, organicResults} of result) {
resultLines.push(## ${searchQuery.term}
);
for (let {title, url, description} of organicResults) {
resultLines.push(- [**${title}**:](${url}) ${description}
);
}
}
return resultLines.join(’\n’);
}
if (searchQuery) {
let results = await searchAsync(searchQuery.split(’,’).map(term => term.trim()).join(’\n’));
await districtTable.updateRecordsAsync(record, {[resultsField.id]: results});
}
}
Oct 21, 2020 10:54 AM
Replying in hopes of following along if you figure out how to do this!
Oct 21, 2020 11:53 AM
First, a quick tip for the forum - when posting code, you can put the code inside triple-backticks (```) to keep the code formatted properly and make it easier to copy-paste code across the forum. So here’s your code cleaned up as I presume it is meant to be, and pasted back into the forum inside an opening and closing (```).
let districtTable = base.getTable("Districts(Education Agencies)");
let districtRecord = await districtTable.selectRecordsAsync();
let record = districtRecord.records[0]
let searchQuery = record.getCellValueAsString("Keywords");
let resultsField = districtTable.getField("Results");
for (let record of districtRecord.records){
async function searchAsync(searchTerm) {
let response = await fetch(
`https://api.apify.com/v2/actor-tasks/EFvVjhi1CSuOfd09L/run-sync-get-dataset-items?token=SsEpDxFwqJ7FgXL2TpN3EmicG`,
{
method: "POST",
headers: {"content-type": "application/json"},
body: JSON.stringify({queries: searchTerm}),
}
);
let result = await response.json();
let resultLines = [];
for (let {searchQuery, organicResults} of result) {
resultLines.push(`## ${searchQuery.term}`);
for (let {title, url, description} of organicResults) {
resultLines.push(`- [**${title}**:](${url}) ${description}`);
}
}
return resultLines.join('\n');
}
if (searchQuery) {
let results = await searchAsync(searchQuery.split(',').map(term => term.trim()).join('\n'));
await districtTable.updateRecordsAsync(record, {[resultsField.id]: results});
}
}
At the top of your script, you are:
Getting your districtTable
.
Then you are getting all the records out of your districtTable
and saving the Query result as districtRecord
. This could presumably contain multiple records (all the records from the districtTable
), but you have it named as a singular - this could be confusing (I might suggest renaming that to districtsQuery
).
Next you are getting the first record from the Query result, and saving it as record
.
Next, you are getting the value of the “Keywords” cell for that first districtTable
record, named record
, and saving that value as searchQuery
Following this, you have a loop that is looping through each record in the districtTable
– for each record, it is checking if there is a value in the variable searchQuery
, and if so, running your searchAsync()
function with searchQuery
as a value to pass to the apify API. However, you are setting the value of searchQuery
only once, outside of your loop. For every single record you loop through, you are using the same value for searchQuery
, namely, the value the of the “Keywords” field for the FIRST record in the districtTable
. So every call to your searchAsync()
function is using the same searchQuery
.
I have a feeling this is not what you mean to do – I have a feeling you mean to retrieve the value of the “Keywords” field for each record as you loop over that record, and have that record’s “Keyword” value be the search query passed to the appify api. Is that right?
Oct 26, 2020 07:17 AM
Hi Jeremy,
Thanks for the tip! Your assumptions are correct. I would like it to run through each record, using the search term within that record.
I got the code to work, running through one record at a time. Thanks!
let districtTable = base.getTable("Districts(Education Agencies)");
let districtsQuery = await districtTable.selectRecordsAsync();
let record = districtsQuery.records[0].id;
let resultsField = districtTable.getField("SearchResults");
output.text ("Searching....")
for (let record of districtsQuery.records){
let searchQuery = record.getCellValueAsString("Keywords");
if (searchQuery) {
let results = await searchAsync(searchQuery.split(',').map(term => term.trim()).join('\n'));
async function searchAsync(searchTerm) {
let response = await fetch(
`https://api.apify.com/v2/actor-tasks/EFvVjhi1CSuOfd09L/run-sync-get-dataset-items?token=SsEpDxFwqJ7FgXL2TpN3EmicG`,
{
method: "POST",
headers: {"content-type": "application/json"},
body: JSON.stringify({queries: searchTerm}),
}
);
let result = await response.json();
let resultLines = [];
for ( let {searchQuery, organicResults} of result) {
resultLines.push(`## ${searchQuery.term}`);
for ( let {title, url, description} of organicResults) {
resultLines.push(`- [**${title}**:](${url}) ${description}`);
}
}
return resultLines.join('\n');
}
await districtTable.updateRecordAsync(record, {SearchResults: results})
}
}
output.text ("search complete.")