【问题标题】:How to use projections in Mongoid?如何在 Mongoid 中使用投影?
【发布时间】:2014-05-11 19:24:13
【问题描述】:

我对 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 查询不同,该查询只返回我正在寻找的一个章节记录。

【问题讨论】:

    标签: mongodb mongoid


    【解决方案1】:

    请在下面找到演示 Mongoid / Moped 中最接近等效项的测试。 Mongoid 和 Moped 的答案都不是“完全相同”的。 对于底层驱动 Moped, 查询结果仍然有包裹在父结构中的章节子文档, 因此需要在客户端在 Ruby 中进行额外的提取。 对于高级 ODM Mongoid, 查询结果是根据定义的父模型, 然后#chapters 关联辅助方法遍历章节, 第二个#where 子句在客户端本地提取。 Mongoid 有 #pluck 方法, 但它只需要一个简单的字段名称, 因此指定点路径会产生意外结果,并在模型级别返回空。

    您可以对测试进行修改以满足您的理解。 希望这会有所帮助。

    test/unit/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 测试

    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
    

    app/models/volume.rb

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

    app/models/chapter.rb

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

    【讨论】:

    • 感谢您的详细回答。我已经达到了实现这一目标的第二种(Mongoid)方法。因为我有多个级别的嵌入,所以我继续进行相同的操作,因为我最终还要迭代中间对象 - Volume.where(query).first.parts.each - 其中 Volume embeds_many Parts,其中 embeds_many Chapters。
    • 这是一个很好的答案。你知道Volume.where(query).first.chapters.where("url" =&gt; "my-chapter").first.attributes 是真的使用位置算子投影,还是使用chapter.urls 上的索引?还是它在内存中做所有事情?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-11
    • 2014-05-11
    • 1970-01-01
    相关资源
    最近更新 更多