2014-05-11 73 views
1

我對MongoDB和Mongoid比較陌生。我的MongoDB的查詢只返回匹配的嵌入式記錄(使用$ projection)看起來像如何在Mongoid中使用投影?

db.volumes.find({"vol": 1, "chapters.url": "my-chapter"}, {"chapters.$": 1}) 

其中嵌入卷許多章節。此查詢還利用我指定的chapters.url字段上的索引。

Mongoid中的上述內容相當於什麼?我試過

Volume.where({vol: 1, "chapters.url" => "my-chapter"}).only(:chapters) 

但僅返回母卷對象,以其超過一個嵌入式章節,不像原來的MongoDB查詢,返回正是一個章記錄我在尋找。

回答

1

請在下面的測試中找到在Mongoid/Moped中最接近的等價物。 Mongoid和Moped的答案都不完全一樣。 對於底層驅動程序Moped, ,查詢結果仍然將章節subdoc包裝在父結構中,因此需要在客戶端的Ruby中額外提取。 對於高級ODM Mongoid ,查詢結果按照定義的父級模型 ,然後#chapters關聯幫助器方法遍歷章節 ,第二個#where子句在客戶端本地提取。 Mongoid擁有#pluck方法, ,但它只需要一個簡單的字段名稱,即 ,因此指定點路徑具有意外的結果,並在模型級別返回空白。

您可以使用測試的修改來滿足您的理解。 希望這有助於。

測試/單位/ volume_test.rb

require 'test_helper' 
require 'pp' 

class VolumeTest < ActiveSupport::TestCase 
    def setup 
    Volume.delete_all 
    puts 
    end 
    test "project" do 
    doc = {vol: 1, chapters: [{url: 'my-chapter'}, {url: 'your-chapter'}]} 
    Volume.create(doc) 
    assert_equal(1, Volume.count) 
    query = {"vol" => 1, "chapters.url" => "my-chapter"} 
    puts "Moped:" 
    result = Volume.collection.find(query).select("chapters.$" => 1).first['chapters'].first 
    assert_equal('my-chapter', result['url']) 
    pp result 
    puts "Mongoid:" 
    result = Volume.where(query).first.chapters.where("url" => "my-chapter").first.attributes 
    assert_equal('my-chapter', result['url']) 
    pp result 
    end 
    test "versions" do 
    puts "Mongoid version: #{Mongoid::VERSION}\nMoped version: #{Moped::VERSION}" 
    puts "MongoDB version: #{Volume.collection.database.command({:buildinfo => 1})['version']}" 
    end 
end 

$耙測試

Run options: 

# Running tests: 

[1/2] VolumeTest#test_project 
Moped: 
{"_id"=>"537274767f11ba1977000002", "url"=>"my-chapter"} 
Mongoid: 
{"_id"=>"537274767f11ba1977000002", "url"=>"my-chapter"} 
[2/2] VolumeTest#test_versions 
Mongoid version: 3.1.6 
Moped version: 1.5.2 
MongoDB version: 2.6.1 
Finished tests in 0.063019s, 31.7365 tests/s, 47.6047 assertions/s. 
2 tests, 3 assertions, 0 failures, 0 errors, 0 skips 

應用程序/模型/ volume.rb

class Volume 
    include Mongoid::Document 
    field :vol, type: Integer 
    embeds_many :chapters 
end 

應用程序/模型/ chapter.rb

class Chapter 
    include Mongoid::Document 
    field :url, type: String 
    embedded_in :volume 
end 
+0

感謝您的詳細解答。我已經達到了你的第二個(Mongoid)實現這個目標的方法。因爲我有多層次的嵌入,我繼續繼續下去,因爲我最終還會對中間對象進行迭代 - 「Volume.where(query).first.parts.each」 - 其中卷embeds_many部分,embeds_many章節。 –

+0

這是一個很好的答案。你知道'Volume.where(query).first.chapters.where(「url」=>「my-chapter」)。first.attributes'實際上是使用positoinal操作符映射,還是使用'chapter.urls '?或者它在記憶中做了什麼? –