【发布时间】:2020-10-21 12:36:55
【问题描述】:
- 我正在尝试从数据库中加载 50000 个包含文本的项目,标记它们并更新标签
- 我为此目的使用 pg-promise 和 pg-query-stream
- 我能够让流式传输部分正常工作,但由于更新语句太多,更新变得有问题
这是我现有的代码
const QueryStream = require('pg-query-stream')
const JSONStream = require('JSONStream')
function prepareText(title, content, summary) {
let description
if (content && content.length) {
description = content
} else if (summary && summary.length) {
description = summary
} else {
description = ''
}
return title.toLowerCase() + ' ' + description.toLowerCase()
}
async function tagAll({ db, logger, tagger }) {
// you can also use pgp.as.format(query, values, options)
// to format queries properly, via pg-promise;
const qs = new QueryStream(
'SELECT feed_item_id,title,summary,content FROM feed_items ORDER BY pubdate DESC, feed_item_id DESC'
)
try {
const result = await db.stream(qs, (s) => {
// initiate streaming into the console:
s.pipe(JSONStream.stringify())
s.on('data', async (item) => {
try {
s.pause()
// eslint-disable-next-line camelcase
const { feed_item_id, title, summary, content } = item
// Process text to be tagged
const text = prepareText(title, summary, content)
const tags = tagger.tag(text)
// Update tags per post
await db.query(
'UPDATE feed_items SET tags=$1 WHERE feed_item_id=$2',
// eslint-disable-next-line camelcase
[tags, feed_item_id]
)
} catch (error) {
logger.error(error)
} finally {
s.resume()
}
})
})
logger.info(
'Total rows processed:',
result.processed,
'Duration in milliseconds:',
result.duration
)
} catch (error) {
logger.error(error)
}
}
module.exports = tagAll
- db 对象是来自 pg-promise 的对象,而标记器只是从变量 tags 中包含的文本中提取标签数组
- 根据我在诊断中看到的情况,正在执行太多更新语句,有没有办法对它们进行批处理?
【问题讨论】:
-
您应该使用multi-row updates,以及Data Imports 中记录的方法。
-
感谢@vitaly-t 多行更新依赖于累积一个大数组并插入所有内容,我担心它会在使用您链接的方法将其注销之前在内存中构建一个非常庞大的数组跨度>
-
Data Import向您展示如何对此类更新进行分区,如果您遵循它。
标签: node.js postgresql stream pg-promise node-postgres