如何在Mongoid中使用投影?

时间:2014-05-11 19:24:13

标签: mongodb mongoid

我是MongoDB和Mongoid的新手。我的MongoDB查询仅返回匹配的嵌入记录(使用$ projection),如

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 个答案:

答案 0 :(得分: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

$ rake test

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