我有以下doc定义(它是红宝石)
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)<{1}} (答案是两个)。
我正在使用b
驱动程序,所以理想情况下查询会使用驱动程序,但是简单的mongo很好。谢谢!
答案 0 :(得分:1)
我认为你要找的是点符号:http://docs.mongodb.org/manual/reference/glossary/#term-dot-notation
问题1:
- 非空/非空代码数组存在多少个块?
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 - 罗布。
编辑:
这不起作用,因为嵌入了块,代码是块内的数组。
我认为我不明白这个问题。 shell返回我期望的内容。
shell中的示例(重新格式化) - 首先是数据:
> 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" : [ ] }
]
}
答案 1 :(得分: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')
根据codes
的大小,保存视频大约需要2 n次插入。但是这些集合是可编制索引的([:num_codes]
为Blocks
而[:position, :value]
为Code
)并且应该为您提供合理的查询性能 - 即使对于大型集合也是如此。希望有所帮助。