我有一份文件,代表一个嵌入许多房间的房子。结构就是这样。
{
description: 'House'
total_price: 1000,
rooms: [{
description: 'Small Single Room',
type: single,
available: true,
price: 300
}, {
description: 'Big Single Room',
type: single,
price: 400,
available: true
}, {
description: 'Another Room',
type: single,
price: 300,
available: true
}]
}
我很难解决这个问题:如何让所有房屋都有单人房,总价700.
要做到这一点,我需要以下内容。
目前我正在努力了解如何做到这一点。我一直在寻找aggregate
和其他方法,但我找不到可行的解决方案。
非常感谢。
答案 0 :(得分:0)
这是您可以使用的一种方法。将剩余房间和剩余价格保存在根级别(初始化为总价格和总房间数)。每当您将房间的可用设置为false时,请从remaining_price和remaining_rooms中减去价格和计数。
{
description: 'House'
total_price: 1000,
remaining_price: 700,
remaining_rooms: 2,
rooms: [{
description: 'Small Single Room',
type: single,
available: false,
price: 300
}, {
description: 'Big Single Room',
type: single,
price: 400,
available: true
}, {
description: 'Another Room',
type: single,
price: 300,
available: true
}]
}
现在您可以简单地查询您想要使用的房间(我正在使用mongoid编写查询,您可以将其转换为您正在使用的任何内容):
House.where(:remaining_price.lte => 700, :remaining_rooms.gte => 2).to_a
答案 1 :(得分:0)
这是一个聚合框架答案。 请注意,第一个$ match会在集合级别过滤文档 并使用$ elemMatch匹配数组元素的类型和可用性。 为了得到房屋可用房间的价格总和, 不可用的房间必然被过滤掉并丢失。 $ group阶段中的添加字段保留数据以供查看, 但是,您的应用可能更适合通过_id获取完整的文档。
希望这能以原始意图回答您的问题 并展示了聚合框架的强大功能。
测试/单元/ house_test.rb
require 'test_helper'
require 'pp'
class HouseTest < ActiveSupport::TestCase
def setup
House.delete_all
end
test "complex aggregate query" do
puts "\nMongoid::VERSION:#{Mongoid::VERSION}\nMoped::VERSION:#{Moped::VERSION}"
total_price_limit = 700
pipeline = [
{'$match' => {'rooms' => {'$elemMatch' => {'type' => 'single', 'available' => true}}}},
{'$unwind' => "$rooms"},
{'$match' => {'rooms.available' => true}},
{'$group' => {
'_id' => '$_id',
'description' => {'$last' => '$description'},
'total_price_available' => {'$sum' => '$rooms.price'},
'rooms' => {'$push' => '$rooms'},
}
},
{'$match' => {'total_price_available' => {'$lte' => total_price_limit}}},
{'$sort' => {'total_price_available' => 1}},
]
docs = [
{
description: 'House 1',
total_price: 1000,
rooms: [{
description: 'Small Single Room',
type: 'single',
available: true,
price: 300
}, {
description: 'Big Single Room',
type: 'single',
price: 400,
available: true
}, {
description: 'Another Room',
type: 'single',
price: 300,
available: true
}]
},
{
description: 'House 2',
total_price: 600,
rooms: [{
description: 'Small Single Room',
type: 'single',
available: true,
price: 300
}, {
description: 'Big Single Room',
type: 'single',
price: 400,
available: false
}, {
description: 'Another Room',
type: 'single',
price: 300,
available: true
}]
}
]
docs.each { |house| House.create(house) }
pp House.collection.aggregate(pipeline)
end
end
$ rake test
Run options:
# Running tests:
[1/1] HouseTest#test_complex_aggregate_query
Mongoid::VERSION:3.1.5
Moped::VERSION:1.5.1
[{"_id"=>"5272dbe2e4d30b7e0a000002",
"description"=>"House 2",
"total_price_available"=>600,
"rooms"=>
[{"description"=>"Small Single Room",
"type"=>"single",
"available"=>true,
"price"=>300},
{"description"=>"Another Room",
"type"=>"single",
"price"=>300,
"available"=>true}]}]
Finished tests in 0.046359s, 21.5708 tests/s, 0.0000 assertions/s.
1 tests, 0 assertions, 0 failures, 0 errors, 0 skips