Couchbase: Как сохранить массивы без дублирующих элементов? - PullRequest
0 голосов
/ 28 ноября 2018

У нас есть магазин Couchbase, в котором есть данные о клиентах.

  • Каждый клиент имеет в своем пакете ровно один документ.
  • Ежедневные транзакции приводят к обновлению данных этого клиента.

Образец документа.Давайте сосредоточимся на массиве paid_product_ids .

{
  "customer_id" : 1000
  "purchased_product_ids" : [1, 2, 3, 4, 5 ] 
      # in reality this is a big array - hundreds of elements
  ... 
  ... many other elements ...
  ...
} 

Existing purchased_product_ids : 
    [1, 2, 3, 4, 5]

products purchased today : 
    [1, 2, 3, 6]  // 6 is a new entry, others existing already

Expected result after the update: 
    [1, 2, 3, 4, 5, 6]

Я использую Subdocument API , чтобы избежать большой передачи данных между сервером и клиентами.

Option1 "arrayAppend":

customerBucket.mutateIn(customerKey)
    .arrayAppend("purchased_product_ids", JsonObject for [1,2,3,6] )
    .execute();

It results in duplicate elements. 
"purchased_product_ids" : [1, 2, 3, 4, 5, 1, 2, 3, 6]

Option2 "arrayAddUnique":

customerBucket.mutateIn(customerKey)
    .arrayAddUnqiue("purchased_product_ids", 1 )
    .arrayAddUnqiue("purchased_product_ids", 2 )
    .arrayAddUnqiue("purchased_product_ids", 3 )
    .arrayAddUnqiue("purchased_product_ids", 6 )
    .execute();

It throws exception for most of the times, 
because those elements already existing.

Есть ли лучший способ сделать это обновление?

Ответы [ 2 ]

0 голосов
/ 28 ноября 2018

Вы можете использовать N1QL и функции ARRAY_APPEND () и ARRAY_DISTINCT ().

UPDATE customer USE KEYS "foo" 
SET purchased_product_ids = ARRAY_DISTINCT(ARRAY_APPEND(purchased_product_ids, 9))

Предположительно, это будет подготовленный оператор, а сам ключ и новое значение будут предоставлены в качестве параметров.

Также, если вы хотите добавить несколько элементов в массив одновременно, ARRAY_CONCAT () будет лучшим выбором.Больше здесь:

https://docs.couchbase.com/server/6.0/n1ql/n1ql-language-reference/arrayfun.html

0 голосов
/ 28 ноября 2018

Нужно ли вам заказать купленные_продукты_id?Если нет, вы можете преобразовать его в карту, например,

{
  "customer_id" : 1000
  "purchased_product_ids" : {1: {}, 3: {}, 5: {}, 2: {}, 4: {}}
}

, а затем написать на эту карту с помощью поддокумента, зная, что вы не будете конфликтовать (при условии уникальности идентификаторов продуктов):

customerBucket.mutateIn(customerKey)
   .upsert("purchased_product_ids.1", JsonObject.create()) // already exists
   .upsert("purchased_product_ids.6", JsonObject.create()) // new product
   .execute();

, что приведет к:

{
  "customer_id" : 1000
  "purchased_product_ids" : {1: {}, 3: {}, 6: {}, 5: {}, 2: {}, 4: {}}
}

(я использовал здесь JsonObject.create () в качестве заполнителя на тот случай, если вам нужно будет связать дополнительную информацию для каждого оплаченного заказа клиента, но вы также можетепросто напишите ноль. Если вам нужно заказать купленные_продукты_id, вы можете написать временную метку заказа, например, 1: {date: <TIMESTAMP>}, а затем упорядочить ее в коде при получении.)

...