简体   繁体   English

Sequelize 对象的原始查询更新数组作为替换

[英]Sequelize raw query update array of objects as replacements

I am using sequelize (postgres) and I need to properly escape a query like this:我正在使用 sequelize (postgres),我需要正确转义这样的查询:

`
       UPDATE "Pets"
       SET "name" = CASE LOWER("name")
         ${input.pets
            .map((pet) => `WHEN '${pet.name.toLowerCase()}' THEN '${pet.newName}'`)
            .join('\n')}
          ELSE "name"
          END
        WHERE LOWER("name") IN(${input.pets
          .map((pet) => `'${pet.name.toLowerCase()}'`)
          .join(',')});
`

Sample input.pets :示例input.pets

[{ name: "rocky", newName: "leo" }]

Does anyone have an idea how to achieve this with replacements?有谁知道如何通过替换来实现这一目标?

I have found a thread on github which suggested something like this:我在 github 上找到了一个线程,它提出了这样的建议:

let data = [ [ 252456, 1, 55, '0' ],
[ 357083, 1, 56, '0' ],
[ 316493, 1, 57, '0' ] ];

db.query(
  `INSERT INTO product (a, b) VALUES ${data.map(a => '(?)').join(',')};`,
  {
     replacements: data,
     type: Sequelize.QueryTypes.INSERT
  }
);

However, a 2d array is being used here not an array of objects.但是,这里使用的是二维数组,而不是对象数组。 Is there a way to access individual properties from the array?有没有办法从数组中访问单个属性? When I try something like this当我尝试这样的事情时

`
       UPDATE "Pets"
       SET "name" = CASE LOWER("name")
         ${input.pets
            .map((_pet) => `WHEN ? THEN ?`)
            .join('\n')}
          ELSE "name"
          END
        WHERE LOWER("name") IN(${input.pets
          .map((_pet) => `?`)
          .join(',')});
`,
    { type: QueryTypes.UPDATE, replacements: input.pets },

The first ?第一个? turns out to be the whole object.原来是整个对象。 Is there a way to access it's properties?有没有办法访问它的属性? I also tried transforming input.pets into a 2d array but still couldn't get it to work as in example with insert above.我还尝试将input.pets转换为 2d 数组,但仍然无法像上面插入的示例那样使其工作。

In advance thanks for your time提前感谢您的时间

    const names = input.pets.map((pet) => pet.name);
    const newNames = input.pets.map((pet) => pet.newName);

`
        UPDATE "Pets"
        SET "name" = CASE LOWER("name")
          ${names.map((_) => `WHEN LOWER(:names) THEN :newNames`).join('\n')}
              ELSE "name"
              END
        WHERE LOWER("name") IN(${names.map((_) => `LOWER(:names)`).join(',')});
`,
      { replacements: { names, newNames } },

This works.这行得通。 In cases like this it's better to work with simpler data structures.在这种情况下,最好使用更简单的数据结构。 Another option I found is using sequelize.escape() built-in function, but it's not documented so I decided not to我发现的另一个选项是使用sequelize.escape()内置函数,但它没有记录,所以我决定不

EDIT: After some testing, this works but for only one object in the input编辑:经过一些测试,这有效,但仅适用于输入中的一个对象

If the input looks something like this:如果输入看起来像这样:

[
        { name: "rocky", newName: "fafik" }
        { name: "asd", newName: "qwerty" }
]

Then in resut I get queries like this:然后我得到这样的查询:

WHEN LOWER('rocky', 'asd') THEN 'fafik', 'qwerty'
WHEN LOWER('rocky', 'asd') THEN 'fafik', 'qwerty'

So it doesn't loop over arrays.所以它不会遍历数组。 Still the problem remains, how to access individual properties, whether from array or an object?问题仍然存在,如何访问单个属性,无论是从数组还是对象?

EDIT2: FINAL ANSWER EDIT2:最终答案

sequelize.query(
  `
    UPDATE "Pets"
    SET "name" = CASE LOWER("name")
      ${input.pets.map(() => `WHEN ? THEN ?`).join('\n')}
         ELSE "name"
         END
    WHERE LOWER("name") IN(?);
  `,
  {
    replacements: [
      ...input.pets.flatMap((x) => [x.name.toLocaleLowerCase(), x.newName]),
      input.pets.map((x) => x.name.toLocaleLowerCase()),
    ],
  },

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM