0

我有以下文档定义(它是红宝石)

class Block
  include Mongoid::Document

  field :index, type: Integer  # index 0,1,..  
  field :codes, type: Array    #[A, B, C,... ]

  embedded_in :Video
end

class Video
  include Mongoid::Document

  field :name, type: String
  embeds_many :blocks, :order => :index.asc
end

我想查询匹配的属性video.blocks.codes,但它是嵌入式文档的数组属性。我主要想做两种类型的查询:

  • 非空/非空codes数组存在多少块?
  • 在代码数组与给定位置的某个字符串匹配的位置存在多少块?

这是我尝试匹配的数据示例:

video#1
blocks: [{index: 1, codes:["a","g","c"]}, {index: 2, codes: [] }]

video#2
blocks: [{index: 1, codes:["x","b","d", "e"]}, {index: 2, codes: ["x","b"] }]

例如,我想知道有多少块没有非空代码数组(答案是三个块),以及在第二个位置(索引 1)有多少块b(答案是有两个)。

我正在使用mongoid驱动程序,所以理想情况下查询将使用驱动程序,但普通的 mongo 很好。谢谢!

4

2 回答 2

1

我认为您正在寻找的是点符号:http ://docs.mongodb.org/manual/reference/glossary/#term-dot-notation

问题一:

  • 非空/非空代码数组存在多少块?
db.videos.find( { 'video.blocks.codes.0' : { $exists : true } } )

实际上是否存在数组的第零个元素。为了速度,您在video.blocks.codes. 另请注意,您将取回一个块内至少包含 1 个非空代码数组的所有视频文档。要计算块,您必须进行客户端处理以删除额外的块。

问题2:

  • 在代码数组与给定位置的某个字符串匹配的位置存在多少块?

非常相似的答案。对于位置 3:

db.videos.find( { 'video.blocks.codes.3' : 'the magic code' } )

抱歉,我不认识 Mongoid,但希望您能翻译以上内容。

HTH - 抢。

编辑:

这不起作用,因为块是嵌入的,而代码是块内的数组。

我想我当时不明白这个问题。外壳返回我所期望的。

来自外壳的示例(重新格式化) - 首先是数据:

> db.test.find()
{ "_id" : ObjectId("51b7cfff0ccc6eb8b11c82b1"), 
  "blocks" : [    
     { "index" : 1, "codes" : [  "a", "g", "c" ] },
     { "index" : 2, "codes" : [ ] } 
  ] 
}
{ "_id" : ObjectId("51b7d0300ccc6eb8b11c82b2"), 
  "blocks" : [
     { "index" : 1, "codes" : [ "x", "b", "d", "e" ] },        
     { "index" : 2, "codes" : [ "x", "b" ] } 
  ] 
}
{ "_id" : ObjectId("51b7d0a50ccc6eb8b11c82b3"), 
  "blocks" : [ 
     { "index" : 1, "codes" : [ ] } 
  ] 
}

第一个查询:查找包含至少 1 个代码块的所有文档:

> db.test.find( { 'blocks.codes.0' : { $exists : true } } )
{ "_id" : ObjectId("51b7cfff0ccc6eb8b11c82b1"), 
  "blocks" : [
     { "index" : 1, "codes" : [ "a", "g", "c" ] },
     { "index" : 2, "codes" : [ ] } 
   ] 
}
{ "_id" : ObjectId("51b7d0300ccc6eb8b11c82b2"), 
  "blocks" : [ 
     { "index" : 1, "codes" : [ "x", "b", "d", "e" ] },
     { "index" : 2, "codes" : [ "x", "b" ] } 
   ] 
}

第二个查询:查找所有第 n 个代码为特定值的文档。在这种情况下,我选择了第二个(索引 1)是“g”。

> db.test.find( { 'blocks.codes.1' : "g" } )
{ "_id" : ObjectId("51b7cfff0ccc6eb8b11c82b1"), 
  "blocks" : [ 
     { "index" : 1, "codes" : [ "a", "g", "c" ] },
     { "index" : 2, "codes" : [ ] } 
  ] 
}
于 2013-06-11T00:49:59.280 回答
0

恕我直言Block,应该是一个带有附加属性的单独集合num_codes(而不是嵌入的,未经测试的代码)。

class Video
    include Mongoid::Document
    has_many :blocks
end

class Block
    include Mongoid::Document
    belongs_to :video
    field :index
    field :num_codes
    field :codes

    # warning pseudo code ahead:
    before_save :update_codes
    def update_codes
       # set num_codes to length of codes
       # delete all codes belonging to this block and recreate them
    end
end

查询空块:Blocks.where(num_codes : 0). 这解决了要求 1。

关于要求 2:据我所知,MongoDB 不允许您在数组中的特定索引处查询值(尽管我在这方面可能是错误的)。同样,我的建议是制作一个单独的集合(未经测试的代码):

class Code
   include Mongoid::Document
   belongs_to :block
   field :position
   field :value
end

Code.where(position : 3, value : 'x')

因此,保存视频将需要大约 2-n 次插入,具体取决于codes. 但是这些集合是可索引的([:num_codes]forBlocks[:position, :value]for Code)并且应该为您提供合理的查询性能 - 即使对于大型集合也是如此。希望有帮助。

于 2013-06-10T22:53:29.173 回答