【问题标题】:How to increment property per document in Sanity?如何在 Sanity 中增加每个文档的属性?
【发布时间】:2018-10-13 17:51:53
【问题描述】:

我们正在建立一个用户可以提交订单的系统。订单具有递增属性deliveryNumber;新订单的 deliveryNumber 应该比前一个订单大一。

在 Sanity 中是否对此有任何内置支持?
如果没有,我们如何才能做到这一点,而又不会因竞争条件而冒着碰撞的风险?

【问题讨论】:

    标签: sanity


    【解决方案1】:

    我刚刚重新发现了这个问题,并认为我应该更新它,因为(一段时间以来)有一种方法可以完全按照您的要求进行:

    这是一个使用Sanity Javascript client的例子:

    const sanityClient = require('@sanity/client')
    const client = sanityClient({
      projectId: 'my-project-id',
      dataset: 'my-dataset',
      token: 'sanity-auth-token',
      useCdn: false
    })
    
    client
      .patch('order-123') // Document ID to patch
      .inc({deliveryNumber: 1}) // Increment field by 1
      .commit() // Perform patch and return a promise
      .then(updatedOrder => {
        console.log('Order delivery number', updatedOrder.deliveryNumber)
      })
      .catch(err => {
        console.error('Ouch. Update failed: ', err.message)
      })

    如果您不是通过 Javascript 访问 Sanity,您可以使用 HTTP API 执行相同的操作。

    【讨论】:

      【解决方案2】:

      据我所知,目前还没有为每个新文档增加属性的内置支持。但是,对于只有一个递增属性的文档(或者如果递增属性都可以从单个递增属性推导出来),您可以自己实现它。

      方法

      为此,我们利用了这样一个事实,即当您创建新文档时,您可以设置 _id 而不是让 Sanity 为您生成它。如果您尝试使用已用于另一个文档的_id 创建文档,则查询将失败。我们将其用作防止竞争条件的机制。

      对于有问题的用例,我们需要做三件事:

      1. 获取最后创建的订单的deliveryNumber(见this answer
      2. 加一得到下一个deliveryNumber
      3. _iddeliveryNumber 创建一个具有相同值的新订单

      如果同时下两个订单,因此尝试创建具有相同deliveryNumber 的两个订单,Sanity 处理的最后一个查询将失败,因为它具有相同的_id第一。只要不失败,每个订单都应该有一个唯一的deliveryNumber,比上一个订单高一个。

      失败时

      如果订单是作为用户交互的结果创建的,我建议让用户知道它失败并要求他们重试。这种情况不会经常发生,而且几乎可以肯定不会连续发生两次。

      但是,如果您必须以编程方式确保重试直到成功,我建议您在重试之前退回一个随机的时间量(每次失败都会成倍增加)。

      生存能力

      创建订单的频率越高,此解决方案的可行性就越低。对于大多数系统,我认为这根本不可能失败。

      【讨论】:

        【解决方案3】:

        现在,可以在架构中包含 initialValues 并允许在架构中设置自动递增值。

        该功能及其工作原理有一个post

        自动递增值

        让我们使用问题的示例,您想要一个交付编号,它是一个递增的数字。

        因此计算每个order 文档并将其加一以将其用作新文档的initialValue

        架构 order.js

        import client from 'part:@sanity/base/client';
        
        export default {
          title: "Order",
          name: "order",
          type: "document",
          initialValue: async () => ({
            deliveryNumber: (await client.fetch(`//groq
               count(*[_type == "order"])
            }) + 1
          }),
          fields: [
            {
              title: "Delivery number",
              name: "deliveryNumber",
              type: "number"
            },
            // other fields
          ]
        }
        

        不确定是否有更简单的方法,但它正在工作。如果我们能有一个助手就好了——比如autoIncrement()

        一种可能的实现方式:

        const autoIncrement = async type = (await client.fetch(`//groq
          count(*[_type == "${type}"])
        }) + 1
        
        // usage:
        {
          // ...,
          initialValue: async () => ({
                deliveryNumber: await autoIncrement("order")
          }),
          // ....
        }
        

        注意: 如果在没有 async/await 并且没有将类型传递给 autoIncrement 的情况下这会很好,但我不确定这是否可能。

        【讨论】:

        • 需要注意的是,initialValue 仅在用户使用 UI 创建新文档时在 Studio 中有效。因此,如果一个计划通过 API 来实现,那么this answer 是可行的方法。
        【解决方案4】:

        阅读以上所有答案后,我提出了一个简单的解决方案来自动提供文档编号。

        首先我像这样为文档编号创建一个字段

        // ...
        {
          name: 'docnum',
          title: 'Document Number',
          type: 'number',
        },
        // ...
        

        然后我在底部创建 initialValue 助手

        import sanityClient from 'part:@sanity/base/client';
        
        // ...
        
        initialValue: async () => {
          const query = '*[_type == "documentName"] | order(_createdAt desc){docnum}';
          const result = await sanityClient.fetch(query);
        
          if (result.length > 0) {
            return { docnum: hasil[0].docnum + 1 };
          } else {
            return { docnum: 1 };
          }
        },
        // ...
        

        使用这种方法,我的第一个文档将具有初始值 docnum 1。后面的文档将具有初始值 last + 1。我正在使用最新版本 btw (1.150.2)

        【讨论】:

          猜你喜欢
          • 2022-11-27
          • 2018-05-23
          • 2015-01-13
          • 2017-07-24
          • 1970-01-01
          • 2012-01-27
          • 2022-11-01
          • 1970-01-01
          • 2020-05-29
          相关资源
          最近更新 更多