javascript - knex 的选择出现意外行为

标签 javascript sql postgresql knex.js

对于以下代码,我得到的结果有时是一个数组,有时是一个对象。我想接收数组,即使它是空的。

export const GetByPId = async (userId, pId) => knex('table1').where({ userId, pId }).select(
  'userId',
  'pId',
  'id',
  'created',
  'updated',
);

在我的业务对象中,我等待响应

static async LoadByPId(userId, pId) {
    const data = await GetByPId(userId, pId);
    console.log(`result ${JSON.stringify(data)}`);
}

一旦它返回

[{ userId: 1, id: 1 ... - 我想要这个

下一次它又回来了

{ userId: 1, id: 1 ... - 不想要这个

这是怎么回事,我怎样才能让它始终返回一个数组?


更新#1

现在它只返回一个结果。


更新 #2

情况每况愈下。

现在我的其他基本功能无法正常工作。 Knex 仅适用于第一组参数,对其他所有参数均无效。

例如,如果 express 服务器重新启动并发送对 userId: 1 和 pId: 1 的请求,它会起作用。如果我用相同的参数重复相同的请求,它就可以工作。但是,如果我将参数(即 userId 或 pId)更改为另一个有效集,它将失败。在尝试任何其他参数之前,我必须重新启动快速服务器。我在我的应用程序和 postman 上对此进行了测试。

我的 express 代码如下所示

router.post('/list', auth, async (req, res) => {
  try {
    const biz= await BizObj.LoadByPId(req.user.id, req.body.pId);
    res.json(biz);
  } catch (ex) {
    console.log(ex);
    res.status(400).json('Unauthorized');
  }
});

更新 #4

如果我的 knex 配置有问题

development: {
    client: 'postgresql',
    connection: {
      database: 'somedb',
      user: 'SOMEUSER',
      password: '',
      timezone: 'UTC',
    },
    pool: {
      min: 2,
      max: 10,
    },
    migrations: {
      tableName: 'knex_migrations',
    },
  },

更新 #5 单页代码(仅缺少快速设置)

在 pg db/SomeObj 中

 id userId
 1  1
 2  2
 3  2

代码示例

import knex from 'knex';
import express from 'express';

const config = {
  development: {
    client: 'pg',
    connection: {
      database: 'somedb',
      user: 'SOMEUSER',
      password: '',
      timezone: 'UTC',
    },
    pool: {
      min: 2,
      max: 10,
    },
    migrations: {
      tableName: 'knex_migrations',
    },
  },
};

const knexed = knex(config.development);
const SQL = knexed('SomeObj');
const GetAll = async userId => SQL.where({ userId }).select(
  'id',
  'userId',
);
const GetById = async (userId, id) => SQL.where({ userId, id }).first(
  'id',
  'userId',
);

class SomeObj {
    constructor(data, userId) {
        this.userId = userId;
        this.id = data.id;
    }
    static async LoadAll(userId) {
        const data = await GetAll(userId);
        if (!data || data.length === 0) return null;
        return data.map(r => new SomeObj(r, userId));
    }
    static async Load(userId, id) {
        const data = await GetById(userId, id);
        if (!data) return null;
        return new SomeObj(data, userId);
    }
}

const router = express.Router();

router.post('/list', async (req, res) => {
  try {
    const res1  = await SomeObj.LoadAll(req.body.id); // works and returns array
    const res2 = await SomeObj.Load(req.body.id, 2); // fails and returns undefined
    res.json({ res1, res2 });
  } catch (ex) {
    res.status(401).json(ex);
  }
});

无法运行第二个查询。不知道我是否遗漏了一些简单的关闭连接的方法。


更新#6

我发誓 knex 在搞乱我。每次我尝试一些东西(并返回确认更改是由于我的新输入)时,都会有不同的响应。现在,res1 和 res2 都为第一个请求返回正确的结果,但第二个请求失败。


更新#7

Runkit 示例:https://runkit.com/tristargod/runkit-npm-knex

它针对第一个请求运行,但对 express 服务器上的所有其他请求都失败。


更新 #8

引用https://github.com/tgriesser/knex/issues/2346#issuecomment-346757344了解更多详情。谢谢米凯尔!

最佳答案

knex('table1')
 .where({ userId, pId })
 .select('userId', 'pId', 'id', 'created', 'updated')

应该总是返回一组结果。您正在做一些示例中未显示的其他错误。

示例代码:https://runkit.com/embed/kew7v2lwpibn

对更新#7 的回应

tldr; Knex 查询生成器是可变的,因此在重新使用它们时 .clone() 是必要的。 https://runkit.com/mikaelle/5a17c6d99cd063001284a20a

很好的例子,从中很容易发现问题👍

您多次重复使用同一个查询构建器,而没有在查询之间克隆它。如果您在设置了 DEBUG=knex:* 环境变量的情况下运行代码,您会发现在第一次调用后构建的查询不正确。

const GetAll = async userId => SQL.clone().where({ userId }).select(
  'id',
  'userId',
);
const GetById = async (userId, id) => SQL.clone().where({ userId, id }).first(
  'id',
  'userId',
);

关于javascript - knex 的选择出现意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47424341/

相关文章:

sql - 查找所有共同作者 - 多对多映射表的分面/分组

javascript - 在 R Shiny 中的垂直 noUiSliderInput 上将标签自定义为指数文本格式

javascript - 如何使用一个 JWT token 签署第二个 JWT token ?

sql - 电子商务网站上非注册用户的订单存储在哪里?

php - 控制 PHP Echo 语句的位置

sql - Oracle 分层查询中放置 PRIOR 语句导致的差异

sql - postgresql,奇怪的 OFFSET/LIMIT 行为(记录顺序)

javascript - 如何将字符串转换为 32 位整数数组?

javascript - 使用 Angular JS 在 HTML 中添加新行

postgresql - 从存储过程中获取标识