Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/446.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用Knex.js创建嵌套的返回模型_Javascript_Node.js_Knex.js_Hapi.js - Fatal编程技术网

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

Javascript 使用Knex.js创建嵌套的返回模型,javascript,node.js,knex.js,hapi.js,Javascript,Node.js,Knex.js,Hapi.js,我使用Knex.js以Hapi.js路由查询MySQL数据库。以下代码可以工作,但需要嵌套查询: { path: '/recipes', method: 'GET', handler: (req, res) => { const getOperation = Knex.from('recipes') // .innerJoin('ingredients', 'recipes.guid', 'ingredients.recipe')

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

{
    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匹配的嵌套对象,这样我就不会有嵌套的承诺?

简短回答:没有

使用Knex,您可以像使用SQL一样检索数据,SQL是基于记录的,而不是基于对象的,因此最接近的方法是使用联接,只允许执行单个选择来检索包含以下元素的单个数组:配方、GUID和配料。这将为每个成分重复配方和guid,通过使用嵌套对象可以避免这种情况。(请参见下面@Fazal的答案,以了解这方面的示例。)

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

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

  • 将路由功能与数据处理分开
  • 另外,将数据操作功能与检索功能分开
  • 使用throw和.catch创建和处理不成功的响应
  • 路由、数据检索、数据操作的分离使得测试、调试和将来的理解更加容易,因为每个函数都有更原子化的用途

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

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

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

    我希望这是有用的!
    Gary。

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

    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);
      })
    

    请参阅..只有几行代码。

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

    import*作为n从“嵌套的knex”导入;
    n、 排列(
    n、 类型({
    id:n.number(“recipe.id”,{id:true}),
    标题:n.string(“recipe.title”),
    成分:n(
    n、 类型({
    id:n.number(“components.id”,{id:true}),
    标题:n.string(“配料名称”)
    })
    )
    })
    )
    .withQuery(
    捏
    .来自(“食谱”)
    .innerJoin(“配料”、“配方.guid”、“配料.配方”)
    .选择()
    .orderBy(“评级”、“说明”)
    .限额(10)
    )
    .然后(配方=>{});
    
    所以食谱甚至有不同的类型

    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);
      })