Szybka odpowiedź brzmi, że zapytanie serwera MongoDB działa tylko na jednej kolekcji. Nie ma łączenia, które przecina zbiory. Pytasz w kolekcji zawartości, ale określając pole należące do kolekcji content_types.
Można użyć osadzania, aby umieścić dwa modele w jednej kolekcji, a następnie zapytanie może działać w odniesieniu do osadzonego dokumentu (podrzędnego) pola.
Mogę podać więcej szczegółów, jeśli chcesz, ale mam nadzieję, że to pozwoli ci przejść przez obecne zdziwienie.
Uzupełnienie na żądanie, bez konieczności osadzania:
Uwaga: Dostęp do danych z wielu kolekcjach będą wymagały wielu zapytań, co najmniej jedno zapytanie za kolekcję.
Poniższy przykład jest oparty na tym, co mogłem wyodrębnić ze swojego wpisu, z modyfikacjami, które działają tak, jak chcesz dla swoich metod. Zapytanie "nie jest równe" korzysta ze znajomości implementacji asocjacji, która jest na razie szybką odpowiedzią, ale struktura linków jest dość oczywista po inspekcji. Należy również zauważyć, że rzeczywiste zapytania Motoroli do MongoDB są wyświetlane w odpowiednim dzienniku Railsów.
Nie znam szczegółów dotyczących plataformatec/has_scope. Mongoid ma swoje własne zakresy, które powinieneś zbadać, jestem gotów pomóc, kiedy tam dotrzesz.
app/models/content_type.rb
class ContentType
include Mongoid::Document
field :name, type: String
has_many :contents
end
app/models/content.rb
class Content
include Mongoid::Document
field :name, type: String
belongs_to :content_type
def self.get_all_content_except_poking_message
Content.where(:name.ne => "no forking, just poking")
end
def self.get_all_content_except_certain_content_type(content_type_name) # 2 queries - one each for ContentType and Content
content_type = ContentType.where(:name => content_type_name).first
Content.where(:content_type_id.ne => content_type.id)
end
end
test/jednostka/content_test.rb
require 'test_helper'
class ContentTest < ActiveSupport::TestCase
def setup
Content.delete_all
ContentType.delete_all
end
test "not equal blogs" do
blogs = ContentType.create(:name => "blogs")
tweets = ContentType.create(:name => "tweets")
blogs.contents << Content.create(:name => "no forking, just poking")
tweets.contents << Content.create(:name => "Kilroy was here")
assert_equal 2, ContentType.count
assert_equal 2, Content.count
puts "all content_types: #{ContentType.all.to_a.inspect}"
puts "all contents: #{Content.all.to_a.inspect}"
puts "get_all_content_except_poking_message: #{Content.get_all_content_except_poking_message.to_a.inspect}"
puts "get_all_content_except_certain_content_type(\"blogs\"): #{Content.get_all_content_except_certain_content_type("blogs").to_a.inspect}"
end
end
testową grabie
Run options:
# Running tests:
[1/1] ContentTest#test_not_equal_blogsall content_types: [#<ContentType _id: 51ded9d47f11ba4ec1000001, name: "blogs">, #<ContentType _id: 51ded9d47f11ba4ec1000002, name: "tweets">]
all contents: [#<Content _id: 51ded9d47f11ba4ec1000003, name: "no forking, just poking", content_type_id: "51ded9d47f11ba4ec1000001">, #<Content _id: 51ded9d47f11ba4ec1000004, name: "Kilroy was here", content_type_id: "51ded9d47f11ba4ec1000002">]
get_all_content_except_poking_message: [#<Content _id: 51ded9d47f11ba4ec1000004, name: "Kilroy was here", content_type_id: "51ded9d47f11ba4ec1000002">]
get_all_content_except_certain_content_type("blogs"): [#<Content _id: 51ded9d47f11ba4ec1000004, name: "Kilroy was here", content_type_id: "51ded9d47f11ba4ec1000002">]
Finished tests in 0.046370s, 21.5657 tests/s, 43.1313 assertions/s.
1 tests, 2 assertions, 0 failures, 0 errors, 0 skips
Na tym prostym przypadku można "uproszczenia" odchodząc od ścisłego relacyjnej normalizacji, na przykład, po prostu dodać "content_type_name" pole do treści z wartościami ciągu, np. "blogi".
Ale aby naprawdę skorzystać z MongoDB, nie powinieneś się wahać.
Mam nadzieję, że to pomoże.
Gary, dzięki za odpowiedź. Jeśli wbudowane powiązanie nie jest opcją, czy istnieje inny sposób na sfałszowanie powiązania? Byłbym bardzo wdzięczny, jeśli podasz przykład kodu dla mojego scenariusza. :) – Annie
Annie, przykład w powyższej odpowiedzi celuje w Twój scenariusz za pomocą odnośników/linków, a nie osadzania. Sprawdź kod dla Content :: get_all_content_except_certain_content_type, który dokładnie odpowiada na twoje pytanie dzięki dwuetapowemu pobieraniu, który jest niezbędny. –