Mongoid - Управление массивом? вставить уникальное значение, удалить значение, если существует? - PullRequest
7 голосов
/ 17 января 2011

Я пытаюсь сделать что-то довольно простое, я верю:

1) вставлять значение в поле массива, только если это значение еще не существует

2) удалить значение, если оно существует в массиве

Я просто не знаю, как сделать что-то из этого ... на данный момент я просто вставляю свое значение, не проверяя, существует ли оно уже: myArray << obj.id </p>

Спасибо

Alex

ps: с использованием Rails 3.0.3, mongo 1.1.5 и mongoid 2.0.0.rc5

ps2: это синтаксис mongodb для достижения того, чего я хочу, но я понятия не имею, как это сделать в mongoid

{ $addToSet : { field : value } }

Добавляет значение в массив только в том случае, если его еще нет в массиве, если поле является существующим массивом, в противном случае задает для поля значение массива, если поле отсутствует. Если поле присутствует, но не является массивом, возникает условие ошибки.

Чтобы добавить много valuest.update

{ $addToSet : { a : { $each : [ 3 , 5 , 6 ] } } }
$pop

{ $pop : { field : 1  } }

удаляет последний элемент в массиве (ДОБАВЛЕНО в 1.1)

{ $pop : { field : -1  } }

удаляет первый элемент в массиве (ДОБАВЛЕНО в 1.1) |

Ответы [ 4 ]

10 голосов
/ 04 апреля 2012

Вы хотите использовать метод add_to_set, как документировано (несколько) здесь: http://mongoid.org/en/mongoid/docs/persistence.html#atomic

Пример:

model = Model.new
model.add_to_set(:field, value)
model.save

Вы можете присвоить ему одно значение или даже массив значений. Последний будет использовать спецификатор $each Монго вместе с $addToSet при добавлении каждого элемента вашего массива в указанное вами поле.

8 голосов
/ 17 января 2011

Согласно Крису Хоку из Mongoid googlegroup:

Массивы в Mongoid документах являются простыми массивами Ruby.См. Документы для класса Array: http://www.ruby -doc.org / core / classes / Array.html

Итак, для вставки вы можете просто сделать:

array << object unless array.include?(object) 

А для удаления:

array.delete(object) 
0 голосов
/ 08 марта 2018

Вы можете использовать оператор вытягивания , который является атомарным, чтобы удалить один элемент.Вот пример, где l является ссылкой на документ с полем массива array:

l.array = [1, 2, 3]
l.save
l.pull(array: 1) # atomically removes 1, leaving [2, 3]

Добавление можно сделать с помощью add_to_set , как упоминалось ранее:

l.array = [2, 3]
l.save
l.add_to_set(array: 1) # atomically adds 1, resulting in [2, 3, 1]

Вот ссылка на текущую Mongoid документацию по атомным операторам.

0 голосов
/ 20 января 2011

стоит упомянуть, в mongoid, начиная с 2.0.0pre4, я не вижу никакой поддержки addToSet. mongo_mapper (хотя imo менее поддерживается :() поддерживает это с помощью метода push_uniq.

Кроме этого, в mongoid, если вы работаете с методом отношений напрямую, вам не нужно делать включение ?. если вы работаете с массивом напрямую, вы делаете.

Пример:

class Person
   include Mongoid::Document
   has_and_belongs_to_many :pets ## or has_many :pets, :stored_as => :array if your not using the latest mongoid 
end

#when using .pets no need to check, mongoid checks for you to ensure you can only add the same pet once.
pet = Pet.find("294x29s9a9292")
p = Person.find("42192189a92191a")
p.pets << pet

#when using pet_ids, you do need to check:
pet = Pet.find("294x29s9a9292")
p = Person.find("42192189a92191a")
p.pet_ids << pet.id unless p.pet_ids.include? pet.id
...