postgresql AdonisJS -更新数组中的许多项

c0vxltue  于 2023-01-13  发布在  PostgreSQL
关注(0)|答案(3)|浏览(146)

所以我使用AdonisJS和PostgreSQL作为我的后端,我试图找到一种方法,通过SQL或使用AdonisJS模型方法,在不执行循环的情况下从数组更新许多数据。
我有一个如下的数组(项目数是不确定的):

[
      {
        "id":5,
        "name":"aaaaaaa",
        "price":"5689.78",
      },

      {
        "id":6,
        "name":"bbbbb",
        "price":"5689.78",
      },

      {
        "id":7,
        "name":"cccc",
        "price":"5689.78",
      }
]

假设我有一个名为products的表

jw5wzhpr

jw5wzhpr1#

所以,我使用了一个带有ONCONFLICT子句的INSERT查询,最终使它工作起来

await Database.raw(
      "INSERT INTO products (id, name, price) " +
      "VALUES (5, 'aaaaaaa', 5689.78), (6, 'bbbbb', 5689.78), (7, 'cccc', 5689.78) " +
      "ON CONFLICT (id) " +
      "DO UPDATE SET " +
      "name = EXCLUDED.name, " +
      "category_id = EXCLUDED.category_id, " +
      "price = EXCLUDED.price, " +
      "units = EXCLUDED.units, " +
      "priority = EXCLUDED.priority, " +
      "is_hidden = EXCLUDED.is_hidden"
    )

为了动态更新它,我将给出以下示例代码

const requestPayload = [
      {
        "id":5,
        "name":"aaaaaaa",
        "price":"5689.78",
      },

      {
        "id":6,
        "name":"bbbbb",
        "price":"5689.78",
      },

      {
        "id":7,
        "name":"cccc",
        "price":"5689.78",
      }
    ]

    // create a string that translate the request payload
    // to this format = "(5, 'aaaaaaa', 5689.78), (6, 'bbbbb', 5689.78), (7, 'cccc', 5689.78)"
    const values = requestPayload.reduce((result, item) => {
      const itemKeys = ['id', 'name', 'price']

      // create a string that translate the product item obj
      // to this format (4, 'aaaa', 111)
      const productValues = itemKeys.reduce((res, productKey) => {
        const productValue = item[productKey]

        if (productKey === 'name') {
          res.push(`'${productValue}'`)
          return res
        }

        res.push(`${productValue}`)

        return res
      }, []).join(', ')

      result.push(`( ${productValues} )`)
      return result
    }, []).join(', ')

    await Database.raw(
      "INSERT INTO products (id, name, price) " +
      "VALUES " + values +
      "ON CONFLICT (id) " +
      "DO UPDATE SET " +
      "name = EXCLUDED.name, " +
      "category_id = EXCLUDED.category_id, " +
      "price = EXCLUDED.price, " +
      "units = EXCLUDED.units, " +
      "priority = EXCLUDED.priority, " +
      "is_hidden = EXCLUDED.is_hidden"
    )

我觉得应该有一个更好的答案使用UPDATE语句而不是INSERT语句,所以如果你有一个更好的答案请回答这个问题!
更新:
现在,我已经使用UPDATE语句创建了一个查询

await Database.raw(
      "UPDATE products " +
      "SET " +
      "name = prod.name, " +
      "price = prod.price, " +
      "FROM " +
      "( VALUES (5, 'aaaaaaa', 5689.78), (6, 'bbbbb', 5689.78), (7, 'cccc', 5689.78) ) as prod (id, name, price) " +
      "WHERE products.id = prod.id"
    )
ubby3x7f

ubby3x7f2#

你可以使用清醒的视角。

const Product = use('App/Models/Product')

const productData = request.collect(['id', 'name', 'price'])
await Product.createMany(productData)

createMany方法执行n个查询,而不是执行大容量插入,其中n是行数。
也可以使用这段代码进行批量插入,但必须显式定义返回的列。

await Database
  .insert(array)
  .into('products')
  .returning('id')
2g32fytz

2g32fytz3#

你可以Map数组的值然后更新

const values = [
      {
        "id":5,
        "name":"aaaaaaa",
        "price":"5689.78",
      },

      {
        "id":6,
        "name":"bbbbb",
        "price":"5689.78",
      },

      {
        "id":7,
        "name":"cccc",
        "price":"5689.78",
      }
]

  values.map(async value =>{
      await Row.merge(value).save()
  })

相关问题