首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Knex.js创建嵌套返回模型

使用Knex.js创建嵌套返回模型
EN

Stack Overflow用户
提问于 2017-11-27 03:39:06
回答 3查看 9.2K关注 0票数 5

我使用Knex.js查询Hapi.js路由中的MySQL数据库。以下代码工作正常,但需要嵌套查询:

代码语言:javascript
复制
{
    path: '/recipes',
    method: 'GET',
    handler: (req, res) => {
        const getOperation = Knex.from('recipes')
        // .innerJoin('ingredients', 'recipes.guid', 'ingredients.recipe')
        .select()
        .orderBy('rating', 'desc')
        .limit(10)
        .then((recipes) => {
            if (!recipes || recipes.length === 0) {
                res({
                    error: true,
                    errMessage: 'no recipes found'
                });
            }

            const recipeGuids = recipes.map(recipe => recipe.guid);
            recipes.forEach(r => r.ingredients = []);
            const getOperation2 = Knex.from('ingredients')
                .whereIn('recipe', recipeGuids)
                .select()
                .then((ingredients) => {
                    recipes.forEach(r => {
                        ingredients.forEach(i => {
                            if (i.recipe === r.guid) {
                                r.ingredients.push(i);
                            }
                        });
                    });
                    res({
                        count: recipes.length,
                        data: recipes
                    });
                });
        });
    }
}

是否有一种方法可以使用Knex.js创建一个返回模型,该模型的嵌套对象与父的id/guid相匹配,从而使我没有嵌套的承诺?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-11-28 01:20:50

简短回答:不。

使用Knex,您可以检索与SQL相同的数据,SQL是基于记录的,而不是基于对象的,所以您可以使用一个join来只进行一个选择来检索具有元素的单个数组:菜谱、guids、成分。这将重复每个成分的配方& guid,您可以通过使用嵌套对象来避免这种情况。(有关此问题的示例,请参见下面@Fazal的回答。)

作为另一种选择,您可以将成分作为“blob”字段存储在配方表中,但我不认为MySQL将允许您创建一个数组字段,因此在检索数据时,必须将字段转换为数组。并在将其更新到表之前将其从Array中转换出来。喜欢:storableData = JSON.stringify(arrayData)arrayData = JSON.parse(storableData)

不过,我还建议您做一些其他的事情来帮助您改进代码。(是的,我知道,这并不是真正的问题):

  1. 将路由功能与数据处理分开。
  2. 此外,将数据操作功能与检索分开。
  3. 使用抛出& .catch来创建和处理不成功的响应。

路由、数据检索、数据操作的分离使得测试、调试和未来理解变得更加容易,因为每个功能都有更多的原子用途。

抛出/.捕获不成功的进程条件使得拥有更全面的错误处理变得更加简单,因为它允许您(大多数情况下)在路由器响应处理中放置一个.catch (Hapi.js甚至可以为您执行此.catch??)。

另外,请参阅我为日志记录错误添加的另一个.catch.on('query-error'。您可能要使用不同的日志机制,而不是控制台。我用温斯顿。请注意,.on('query-error'不是.catch。仍然会抛出一个错误(),并且必须在某个地方进行处理,这只会给您提供与源附近的故障有关的良好信息。

(对不起,下面的代码未经测试)

代码语言:javascript
复制
path: '/recipes',
method: 'GET',
handler: (req, res) => {
        return getRecipeNIngredients()
            .then((recipes) => {
                res({
                    count: recipes.length,
                    data: recipes
                });
            })
            .catch((ex) => {
                res({
                    error: true,
                    errMessage: ex.message
                });
            });
};

    function getRecipeNIngredients() {
        let recipes = null;
        return getRecipes()
            .then((recipeList) => {
                recipes = recipeList;
                const recipeGuids = recipes.map(recipe => recipe.guid);
                recipes.forEach(r => r.ingredients = []);
                return getIngredients(recipeGuids);
            })
            .then((ingredients) => {
                recipes.forEach(r => {
                    ingredients.forEach(i => {
                        if (i.recipe === r.guid) {
                            r.ingredients.push(i);
                        }
                    });
                });
                return recipes;
            })
            .catch((ex) => {
                console.log(".getRecipeNIngredients ERROR ex:",ex); // log and rethrow error.
                throw ex;
            });
    };

    function getRecipes() {
        return Knex.from('recipes')
            // .innerJoin('ingredients', 'recipes.guid', 'ingredients.recipe')
            .select()
            .orderBy('rating', 'desc')
            .limit(10)
            .on('query-error', function(ex, obj) {
                console.log("KNEX getRecipes query-error ex:", ex, "obj:", obj);
            })
            .then((recipes) => {
                if (!recipes || recipes.length === 0) {
                    throw new Error('no recipes found')
                }
            })
    };
    function getIngredients(recipeGuids) {
        return Knex.from('ingredients')
            .whereIn('recipe', recipeGuids)
            .select()
            .on('query-error', function(ex, obj) {
                console.log("KNEX getIngredients query-error ex:", ex, "obj:", obj);
            })
    };

我希望这是有用的!加里。

票数 6
EN

Stack Overflow用户

发布于 2019-11-26 08:56:42

我创建了一个库,它返回嵌套对象,即使它有类型的类型。

巢式Knex

代码语言:javascript
复制
import * as n from 'nested-knex';

n.array(
  n.type({
    id: n.number("recipe.id", { id: true }),
    title: n.string("recipe.title"),
    ingredients: n.array(
      n.type({
        id: n.number("ingredients.id", { id: true }),
        title: n.string("ingredients.title")
      })
    )
  })
)
  .withQuery(
    knex
      .from("recipes")
      .innerJoin("ingredients", "recipes.guid", "ingredients.recipe")
      .select()
      .orderBy("rating", "desc")
      .limit(10)
  )
  .then(recipes => {});

所以菜谱甚至有类型

票数 1
EN

Stack Overflow用户

发布于 2017-11-28 18:16:56

您可以轻松地避免嵌套查询。只需使用子查询作为-

代码语言:javascript
复制
knex.select('*')
  .from(function () {
    this.select('*').from('recipes').limit(10).as('recipes'); // limit here
  })
  .leftJoin('ingredients', 'ingredients.recipe_id', 'recipes.guid')
  .then((rec) => {
    console.log(rec);
  })

你看..。只有几行代码。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47503627

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档