1

我有一个文件代表一个嵌入许多房间的房子。结构是这样的。

{
   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其他方法,但找不到有效的解决方案。

非常感谢。

4

2 回答 2

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

$耙子测试

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
于 2013-10-31T22:42:31.027 回答
0

这是您可以使用的一种方法。在根级别保存剩余房间和剩余价格(使用总价格和总房间进行初始化)。每当您将房间设置为 false 时,从剩余价格和剩余房间中减去价格和计数。

{
   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

于 2013-10-22T20:15:11.353 回答