使用 Firestore Cloud Function 将所有记录导出到 Algolia 索引
export all records to Algolia index with Firestore Cloud Function
我坚持使用 Firestore Cloud Function 获取所有现有文档并在 Algolia 中为它们编制索引的语法。我真的只想做一次,但如果能理解如何做就太好了。
我在 index.js 顶部的配置是:
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateCustomerReportLink = exports.createUser = exports.helloWorld = void 0;
const functions = require("firebase-functions");
const admin = require("firebase-admin");
const algoliasearch = require('algoliasearch')
admin.initializeApp();
const actionCodeSettings = {
// URL you want to redirect back to. The domain (www.example.com) for
// this URL must be whitelisted in the Firebase Console.
url: 'https://www.myurl.com',
// This must be true for email link sign-in.
handleCodeInApp: true,
};
const ALGOLIA_ID = functions.config().algolia.app;
const ALGOLIA_ADMIN_KEY = functions.config().algolia.api_key;
// const ALGOLIA_SEARCH_KEY = functions.config().algolia.search_key;
const client = algoliasearch(ALGOLIA_ID, ALGOLIA_ADMIN_KEY);
const ALGOLIA_INDEX_NAME = 'Sessions';
const index = client.initIndex(ALGOLIA_INDEX_NAME);
我能找到的所有文档要么不使用云函数,要么像这些示例中那样使用像 onWrite 这样的云函数触发器 cloud function examples
看起来像语法
exports.indexentry = functions.database.ref('/blog-posts/{blogid}/text').onWrite(
只适用于触发方式?
我目前已设置并运行函数,并且我的 algolia 配置已正确设置,因为我有一个由 onCreate 触发的云函数,它在 algolia 中创建了一个新索引并且效果很好。
我尝试编写的函数代码是这样的:
const ALGOLIA_ID = functions.config().algolia.app;
const ALGOLIA_ADMIN_KEY = functions.config().algolia.api_key;
// const ALGOLIA_SEARCH_KEY = functions.config().algolia.search_key;
const client = algoliasearch(ALGOLIA_ID, ALGOLIA_ADMIN_KEY);
const ALGOLIA_INDEX_NAME = 'Sessions';
const index = client.initIndex(ALGOLIA_INDEX_NAME);
const _collection = admin.firestore().collection('sessions');
exports.sendCollectionToAlgolia = functions._collection.once('value', sessions => {
// Build an array of all records to push to Algolia
const records = [];
sessions.forEach(session => {
// get the key and data from the snapshot
const childKey = session.key;
const childData = session;
// We set the Algolia objectID as the Firebase .key
childData.objectID = childKey;
// Add object for indexing
records.push({
sessionDate: childData.sessionDate,
customer1FirstName: childData.customer1FirstName,
customer1LastName: childData.customer1LastName
});
});
// Add or update new objects
index
.saveObjects(records)
.then(() => {
console.log('Contacts imported into Algolia');
})
.catch(error => {
console.error('Error when importing contact into Algolia', error);
process.exit(1);
});
});
但是我在部署时遇到错误:
TypeError: Cannot read property 'database' of undefined
如果我将此代码用于我的云函数,它基于此处的代码示例 algolia docs firestore examples 函数部署,但是当我在浏览器中调用测试函数 url 时,我得到 408并且请求超时。
exports.sendCollectionToAlgolia = functions.https.onRequest(async (req, res) => {
// This array will contain all records to be indexed in Algolia.
// A record does not need to necessarily contain all properties of the Firestore document,
// only the relevant ones.
const algoliaRecords = [];
// Retrieve all documents from the COLLECTION collection.
const querySnapshot = await admin.firestore().collection('Sessions').get();
querySnapshot.docs.forEach(doc => {
const document = doc.data();
// Essentially, you want your records to contain any information that facilitates search,
// display, filtering, or relevance. Otherwise, you can leave it out.
const record = {
objectID: doc.id,
sessionDate: document.sessionDate,
customer1FirstName: document.customer1FirstName,
customer1LastName: document.customer1LastName
};
algoliaRecords.push(record);
});
// After all records are created, we save them to
index.saveObjects(algoliaRecords, (_error, content) => {
res.status(200).send("COLLECTION was indexed to Algolia successfully.");
});
})
对于:
TypeError: Cannot read property 'database' of undefined
您正在使用实时数据库语法。对于 Firestore 它将是:
exports.indexentry = functions.firestore.document('/blog-posts/{blogid}/text').onWrite(
相关文档是 here
我有一些错误。大多数错误原来是一个简单的 js 错误,其中传递给 saveObjects() 函数的列表的长度始终为 0,因此我更改了列表的范围并将其链接到承诺中 then:
const runtimeOpts = {
timeoutSeconds: 540,
memory: '1GB'
}
// Get all sessions from Firebase
exports.sendCollectionToAlgolia = functions.runWith(runtimeOpts).https.onRequest(async (req, res) => {
admin.firestore().collection("sessions").get().then((docs) => {
let _sessions = [];
docs.forEach((doc) => {
let session = doc.data();
const childKey = doc.id;
if (
session.customerInfo.customers.customer1.customerFirstName &&
session.customerInfo.customers.customer1.customerLastName
) {
const childData = {
indexData: {
sessionDate: session.sessionDate,
customer1FirstName: session.customerInfo.customers.customer1.customerFirstName,
customer1LastName: session.customerInfo.customers.customer1.customerLastName,
}
}
childData.objectID = childKey;
_sessions.push(childData);
}
})
return _sessions;
}).then((_sessions) => {
index.saveObjects(_sessions)
.then(() => {
console.log('Contacts imported into Algolia');
})
.catch(error => {
console.error('Error when importing contact into Algolia', error);
process.exit(1);
});
})
});
附带说明 - 记录整个文档字段数组仅在文档非常小的情况下才有效。在云函数控制台中记录任何内容的全部输出是个坏主意!
我坚持使用 Firestore Cloud Function 获取所有现有文档并在 Algolia 中为它们编制索引的语法。我真的只想做一次,但如果能理解如何做就太好了。
我在 index.js 顶部的配置是:
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateCustomerReportLink = exports.createUser = exports.helloWorld = void 0;
const functions = require("firebase-functions");
const admin = require("firebase-admin");
const algoliasearch = require('algoliasearch')
admin.initializeApp();
const actionCodeSettings = {
// URL you want to redirect back to. The domain (www.example.com) for
// this URL must be whitelisted in the Firebase Console.
url: 'https://www.myurl.com',
// This must be true for email link sign-in.
handleCodeInApp: true,
};
const ALGOLIA_ID = functions.config().algolia.app;
const ALGOLIA_ADMIN_KEY = functions.config().algolia.api_key;
// const ALGOLIA_SEARCH_KEY = functions.config().algolia.search_key;
const client = algoliasearch(ALGOLIA_ID, ALGOLIA_ADMIN_KEY);
const ALGOLIA_INDEX_NAME = 'Sessions';
const index = client.initIndex(ALGOLIA_INDEX_NAME);
我能找到的所有文档要么不使用云函数,要么像这些示例中那样使用像 onWrite 这样的云函数触发器 cloud function examples
看起来像语法
exports.indexentry = functions.database.ref('/blog-posts/{blogid}/text').onWrite(
只适用于触发方式?
我目前已设置并运行函数,并且我的 algolia 配置已正确设置,因为我有一个由 onCreate 触发的云函数,它在 algolia 中创建了一个新索引并且效果很好。
我尝试编写的函数代码是这样的:
const ALGOLIA_ID = functions.config().algolia.app;
const ALGOLIA_ADMIN_KEY = functions.config().algolia.api_key;
// const ALGOLIA_SEARCH_KEY = functions.config().algolia.search_key;
const client = algoliasearch(ALGOLIA_ID, ALGOLIA_ADMIN_KEY);
const ALGOLIA_INDEX_NAME = 'Sessions';
const index = client.initIndex(ALGOLIA_INDEX_NAME);
const _collection = admin.firestore().collection('sessions');
exports.sendCollectionToAlgolia = functions._collection.once('value', sessions => {
// Build an array of all records to push to Algolia
const records = [];
sessions.forEach(session => {
// get the key and data from the snapshot
const childKey = session.key;
const childData = session;
// We set the Algolia objectID as the Firebase .key
childData.objectID = childKey;
// Add object for indexing
records.push({
sessionDate: childData.sessionDate,
customer1FirstName: childData.customer1FirstName,
customer1LastName: childData.customer1LastName
});
});
// Add or update new objects
index
.saveObjects(records)
.then(() => {
console.log('Contacts imported into Algolia');
})
.catch(error => {
console.error('Error when importing contact into Algolia', error);
process.exit(1);
});
});
但是我在部署时遇到错误:
TypeError: Cannot read property 'database' of undefined
如果我将此代码用于我的云函数,它基于此处的代码示例 algolia docs firestore examples 函数部署,但是当我在浏览器中调用测试函数 url 时,我得到 408并且请求超时。
exports.sendCollectionToAlgolia = functions.https.onRequest(async (req, res) => {
// This array will contain all records to be indexed in Algolia.
// A record does not need to necessarily contain all properties of the Firestore document,
// only the relevant ones.
const algoliaRecords = [];
// Retrieve all documents from the COLLECTION collection.
const querySnapshot = await admin.firestore().collection('Sessions').get();
querySnapshot.docs.forEach(doc => {
const document = doc.data();
// Essentially, you want your records to contain any information that facilitates search,
// display, filtering, or relevance. Otherwise, you can leave it out.
const record = {
objectID: doc.id,
sessionDate: document.sessionDate,
customer1FirstName: document.customer1FirstName,
customer1LastName: document.customer1LastName
};
algoliaRecords.push(record);
});
// After all records are created, we save them to
index.saveObjects(algoliaRecords, (_error, content) => {
res.status(200).send("COLLECTION was indexed to Algolia successfully.");
});
})
对于:
TypeError: Cannot read property 'database' of undefined
您正在使用实时数据库语法。对于 Firestore 它将是:
exports.indexentry = functions.firestore.document('/blog-posts/{blogid}/text').onWrite(
相关文档是 here
我有一些错误。大多数错误原来是一个简单的 js 错误,其中传递给 saveObjects() 函数的列表的长度始终为 0,因此我更改了列表的范围并将其链接到承诺中 then:
const runtimeOpts = {
timeoutSeconds: 540,
memory: '1GB'
}
// Get all sessions from Firebase
exports.sendCollectionToAlgolia = functions.runWith(runtimeOpts).https.onRequest(async (req, res) => {
admin.firestore().collection("sessions").get().then((docs) => {
let _sessions = [];
docs.forEach((doc) => {
let session = doc.data();
const childKey = doc.id;
if (
session.customerInfo.customers.customer1.customerFirstName &&
session.customerInfo.customers.customer1.customerLastName
) {
const childData = {
indexData: {
sessionDate: session.sessionDate,
customer1FirstName: session.customerInfo.customers.customer1.customerFirstName,
customer1LastName: session.customerInfo.customers.customer1.customerLastName,
}
}
childData.objectID = childKey;
_sessions.push(childData);
}
})
return _sessions;
}).then((_sessions) => {
index.saveObjects(_sessions)
.then(() => {
console.log('Contacts imported into Algolia');
})
.catch(error => {
console.error('Error when importing contact into Algolia', error);
process.exit(1);
});
})
});
附带说明 - 记录整个文档字段数组仅在文档非常小的情况下才有效。在云函数控制台中记录任何内容的全部输出是个坏主意!