gpt4 book ai didi

node.js - 如何检查给定查询是否在 knex 中返回任何结果

转载 作者:太空宇宙 更新时间:2023-11-04 03:22:55 24 4
gpt4 key购买 nike

我有两个疑问:

a) 从 ingrdietns 中选择 id,其中 name = my_param;

b) 从同义词中选择 word_id,其中 name = my_param;

两者都返回 0 或 1 行。如果需要(或在 knex first() 中),我还可以添加 limit 1

我可以将每个都翻译成 knex,如下所示:

knex("ingredients").select('id').where('name', my_param) //do we need first()?

knex("synonyms").select('word_id').where('name', my_param) //do we need first()?

我需要名为“ingredientGetOrCreate(my_param)”的函数。这个函数将

a) 检查以上查询是否返回结果b) 如果其中任何一个返回,则返回配料.id 或同义词.word_id - 只能返回一个c) 如果记录没有出现在任何表中,我需要执行 knex inesrt a 并从函数返回新添加的 id

d) 后来我不确定我是否也理解如何调用这个新创建的函数。函数 ingredientGetOrCreate 稍后将用作单独的函数,或者在以下场景(如“循环”)中使用,但对我来说也不起作用:

knex("products") // for each product
.select("id", "name")
.map(function (row) {
var descriptionSplitByCommas = row.desc.split(",");
Promise.all(descriptionSplitByCommas
.map(function (my_param) {
// here it comes - call method for each param and do insert
ingredientGetOrCreate(my_param)
.then(function (id_of_ingredient) {
knex('ingredients_products').insert({ id_of_ingredient });

});
...

由于异步部分,我陷入了 knexPromise 查询的困境。请问有什么线索吗?我虽然可以以某种方式使用 Promise.allPromise.some 来调用这两个查询。

附注这是我第一天使用 Nodejs、Promise 和 knex。

最佳答案

据我解码您的问题,它由两部分组成:

(1) 您需要实现 upsert逻辑(get-or-create逻辑)。

(2) 您的get部分要求查询的不是单个表,而是按特定顺序查询一对表。表名称暗示这是应用程序内部的某种别名引擎。

我们从 (2) 开始。这肯定可以通过两个查询来解决,就像您感觉到的那样。

function pick_name (rows)
{
if (! rows.length) return null
return rows[0].name
}

// you can sequence queries
function ingredient_get (name)
{
return knex('ingredients')
.select('id').where('name', name)
.then(pick_name)
.then(name =>
{
if (name) return name

return knex('synonyms')
.select('word_id').where('name', name)
.then(pick_name)
})
}

// or run em parallel
function ingredient_get (name)
{
var q_ingredients = knex('ingredients')
.select('id').where('name', name)
.then(pick_name)

var q_synonyms = knex('synonyms')
.select('word_id').where('name', name)
.then(pick_name)

return Promise.all([ q_ingredients, q_synonyms ])
.then(([name1, name2]) =>
{
return name1 || name2
})
}

这里的重要概念:

  • 两种形式都运行良好,并返回第一次出现或 JS' null .
  • 第一种形式优化了对数据库的查询数量。
  • 第二种形式可以优化回答时间。

但是,您可以更深入并使用更多 SQL。有一个专门的工具可以完成此类任务,称为 COALESCE 。你可以查阅你的SQL文档,这里是COLASCE of PostgreSQL 9COALESCE的主要思想是返回第一个非 NULL 参数,否则返回 NULL。因此,您可以利用它来优化查询和应答时间。

function ingredient_get (name)
{
// preparing but not executing both queries
var q_ingredients = knex('ingredients')
.select('id').where('name', name)

var q_synonyms = knex('synonyms')
.select('word_id').where('name', name)

// put them in COALESCE
return knex.raw('SELECT COALESCE(?, ?) AS name', [ q_ingredients, q_synonyms ])
.then(pick_name)

该解决方案保证单个查询,此外数据库引擎可以以其认为合适的任何方式优化执行。

现在让我们解决 (1):我们现在得到 ingredient_get(name)返回 Promise<string | null> 。我们可以使用它的输出来激活 create逻辑或返回我们的值。

function ingredient_get_or_create (name, data)
{
return ingredient_get(name)
.then(name =>
{
if (name) return name

// …do your insert logic here
return knex('ingredients').insert({ name, ...data })
// guarantee homohenic output across get/create calls:
.then(() => name)
})
}

现在ingredient_get_or_create执行您想要的更新插入逻辑。

UPD1:我们已经得到了ingredient_get_or_create返回 Promise<name>在任何情况下(获取或创建)。

a) 如果您之后需要执行任何特定逻辑,则可以使用 then :

ingredient_get_or_create(…)
.then(() => knex('another_table').insert(…))
.then(/* another logic after all */)

在 promise 语言中,这意味着“如果之前的操作没问题,则执行该操作(then)”。在大多数情况下,这就是您所需要的。

b) 要在 Promise 中实现 for 循环,您有多种不同的习惯用法:

// use some form of parallelism
var qs = [ 'name1', 'name2', 'name3' ]
.map(name =>
{
return ingredient_get_or_create(name, data)
})

var q = Promise.all(qs)

请注意,这是一种积极的并行性,您将获得输入数组提供的最大并行查询。

如果不需要,您需要限制并行性,甚至顺序运行任务。 bluebird 的Promise.map是运行 ingredient_get_or_create 的一种方式与上面的示例类似,但带有 map可用选项。请考虑文档以获取详细信息。

还有 bluebird 的 Promise.mapSeries从概念上讲,它类似于 for 循环,但带有 promise 。它就像顺序运行的 map 。有关详细信息,请参阅文档。

Promise.mapSeries([ 'name1', 'name2', 'name3' ],
(name) => ingredient_get_or_create(name, data))
.then(/* logic after all mapSeries are OK */)

我相信最后一个就是您所需要的。

关于node.js - 如何检查给定查询是否在 knex 中返回任何结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48170012/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com