我正在尝试运行一个lambda,每次将对象放入我的S3存储桶时,该数据就会将元数据插入到数据库中。
因为我使用的是MongoDB,所以我有代码可以在两次调用之间保持数据库连接。我遇到的问题是我无法获取元数据。
所有插入数据库的代码都已完成,我只需要帮助就可以从aws lambda中获取元数据。
这是我的代码(大部分是从MongoDB site复制而来的)
"use strict";
const MongoClient = require('mongodb').MongoClient;
const MONGODB_URI = 'mongodb://cam_writer:1%40kGM%26LL%26gA5y7NVk1cvl9@cluster0-shard-00-00-hlygq.mongodb.net:27017,cluster0-shard-00-01-hlygq.mongodb.net:27017,cluster0-shard-00-02-hlygq.mongodb.net:27017/test?ssl=true&replicaSet=Cluster0-shard-0&authSource=admin&retryWrites=true'; // or Atlas connection string
var AWS = require('aws-sdk')
var s3 = AWS.S3()
let cachedDb = null;
function connectToDatabase (uri) {
console.log('=> connect to database');
if (cachedDb) {
console.log('=> using cached database instance');
return Promise.resolve(cachedDb);
}
return MongoClient.connect(uri)
.then(client => {
cachedDb = client.db('events');
return cachedDb;
});
}
function queryDatabase (db) {
console.log('=> query database');
return db.collection('detection_events').find({}).toArray()
.then(() => { return { statusCode: 200, body: 'success' }; })
.catch(err => {
console.log('=> an error occurred: ', err);
return { statusCode: 500, body: 'error' };
});
}
function insertIntoDb (db, obj) {
console.log('=> inserting data into db');
return db.collection('detection_events').insertOne(obj)
}
module.exports.handler = (event, context, callback) => {
context.callbackWaitsForEmptyEventLoop = false;
console.log(event)
var meta = {test : "test", "key": event}; // HOW DO I GET THE ACTUAL METADATA FOR THE EVENT?
console.log('event: ', event);
connectToDatabase(MONGODB_URI)
.then(db => insertIntoDb(db, meta))
.then(result => {
console.log('=> returning result: ', result);
callback(null, result);
})
.catch(err => {
console.log('=> an error occurred: ', err);
callback(err);
});
};
我知道s3传递给lambda的“事件”不包含元数据。在python中,我能够使用boto3获取元数据,我只是不知道如何在node.js中进行操作((在AWS Lambda中更不用说node.js了)
编辑:
所以我已经按照下面的第一个答案更新了我的代码。现在的代码是:
"use strict";
const MongoClient = require('mongodb').MongoClient;
const MONGODB_URI = 'mongodb://cam_writer:1%40kGM%26LL%26gA5y7NVk1cvl9@cluster0-shard-00-00-hlygq.mongodb.net:27017,cluster0-shard-00-01-hlygq.mongodb.net:27017,cluster0-shard-00-02-hlygq.mongodb.net:27017/test?ssl=true&replicaSet=Cluster0-shard-0&authSource=admin&retryWrites=true'; // or Atlas connection string
const AWS = require('aws-sdk')
const s3 = new AWS.S3()
let cachedDb = null;
const connectToDatabase = uri => {
console.log('=> connect to database');
if (cachedDb) {
console.log('=> using cached database instance');
return Promise.resolve(cachedDb);
}
return MongoClient.connect(uri)
.then(client => {
cachedDb = client.db('events');
return Promise.resolve(cachedDb);
});
}
function insertIntoDb(db, obj) {
console.log('=> inserting data into db');
return db.collection('detection_events').insertOne(obj)
}
module.exports.handler = async (event) => {
const db = await connectToDatabase(MONGODB_URI);
//finally get the HEAD for the s3Object
const head = await s3.headObject({
Bucket: event.Records[0].s3.bucket.name,
Key: event.Records[0].s3.object.key
}).promise();
var meta = head['Metadata']
meta['bucket'] = event.Records[0].s3.bucket.name,
meta['key'] = event.Records[0].s3.object.key
console.log(meta)
const result = await insertIntoDb(db, meta)
console.log(result)
return {
statusCode: 201,
body: JSON.stringify(result)
}
};
我运行了代码,它将一堆图像插入s3中。这在mongodb中大约有25个连接,我如何通过lambda保持低连接?我认为从mongoDB网站复制的代码将允许我这样做
答案 0 :(得分:1)
由于您正在使用S3事件,因此可以通过访问event.Records[0].s3.bucket.name
和event.Records[0].s3.object.key
来获取s3 bucket 和 key 。可以使用以下代码轻松完成此操作:
const params = {
Bucket: event.Records[0].s3.bucket.name,
Key: event.Records[0].s3.object.key
};
s3.headObject(params, function(err, data) {
if (err) {
console.log(err, err.stack);
return;
}
console.log(data)
});
只需确保将其放入数据库回调中,否则将无法对其进行跟踪。
不过,我强烈建议您使用async/await,因为您不必处理著名的callback hell。这是重构的代码:
"use strict";
const MongoClient = require('mongodb').MongoClient;
const MONGODB_URI = 'mongodb://cam_writer:1%40kGM%26LL%26gA5y7NVk1cvl9@cluster0-shard-00-00-hlygq.mongodb.net:27017,cluster0-shard-00-01-hlygq.mongodb.net:27017,cluster0-shard-00-02-hlygq.mongodb.net:27017/test?ssl=true&replicaSet=Cluster0-shard-0&authSource=admin&retryWrites=true'; // or Atlas connection string
const AWS = require('aws-sdk')
const s3 = AWS.S3()
let cachedDb = null;
const connectToDatabase = uri => {
console.log('=> connect to database');
if (cachedDb) {
console.log('=> using cached database instance');
return Promise.resolve(cachedDb);
}
return MongoClient.connect(uri)
.then(client => {
cachedDb = client.db('events');
return Promise.resolve(cachedDb);
});
}
function insertIntoDb (db, obj) {
console.log('=> inserting data into db');
return db.collection('detection_events').insertOne(obj)
}
module.exports.handler = async (event) => {
const db = await connectToDatabase(MONGODB_URI);
const result = await insertIntoDb(db, {
bucket: event.Records[0].s3.bucket.name,
key: event.Records[0].s3.object.key
})
console.log(result)
//finally get the HEAD for the s3Object
const head = await s3.headObject({
Bucket: event.Records[0].s3.bucket.name,
Key: event.Records[0].s3.object.key
}).promise();
console.log(head)
return {
statusCode: 201,
body: JSON.stringify(result)
}
};
这应该足以让您脱离现实。
编辑:我建议您看看official NodeJS SDK,因为它的文档非常好
编辑2 :根据Michael's的建议,如果文件中可能包含空格,请使用decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, " "))
代替event.Records[0].s3.object.key
编辑3 :现在您的代码可以正常工作了,您说它向S3添加了图像“束”。 S3将触发与插入图像一样多的事件。这意味着N个Lambda将同时启动,因此每次都创建一个新的MongoDB连接。
这里的一种解决方法是将Lambda函数上的并发执行限制设置为一个较小的数字,以便您可以控制同时打开多少个连接。
要执行此操作,请转到Lambda的控制台,并将Concurrency设置为所需的任何数字(在下面的示例中,我使用5)。这应该足以满足您的需求。