【问题标题】:Multiple indexes query in Boost Multi-IndexBoost Multi-Index 中的多索引查询
【发布时间】:2015-08-01 19:36:24
【问题描述】:

我正在编写一个将 GenericOrder(包含数量、价格、方式和时间戳)存储为 shared_ptr 的软件。
我已阅读 Boost 文档并成功定义了一个 MultiIndexOrderContainer 使用三个索引:方式、时间戳和价格。
但我没有找到同时使用多个索引迭代特定订单的方法。

#include <memory>

#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/member.hpp>

using namespace ::boost;
using namespace ::boost::multi_index;

enum class Way
{
    UNDEFINED,
    BUY,
    SELL
};

template <typename QuantityType, typename PriceType>
struct GenericOrder
{
    explicit GenericOrder(const Way way, const QuantityType& quantity, const PriceType& price, const long long& timestamp)
        : way_(way), quantity_(quantity), price_(price), timestamp_(timestamp)
    {
    }

    ~GenericOrder() = default;
    GenericOrder(const GenericOrder&) = delete;
    GenericOrder& operator=(const GenericOrder&) = delete;

    Way way_;
    QuantityType quantity_;
    PriceType price_;
    long long timestamp_ = -1;
};

// Aliases
using QuantityType = int;
using PriceType = int;
using OrderType = GenericOrder<QuantityType, PriceType>;
using PointerType = std::shared_ptr<OrderType>;

struct way {};
struct timestamp {};
struct price {};

using MultiIndexOrderContainer = multi_index_container<PointerType,
    indexed_by<
    ordered_non_unique<tag<way>, member<OrderType, decltype(OrderType::way_), &OrderType::way_ >>,
    ordered_non_unique<tag<timestamp>, member<OrderType, decltype(OrderType::timestamp_), &OrderType::timestamp_ >>,
    ordered_non_unique<tag<price>, member<OrderType, decltype(OrderType::price_), &OrderType::price_>>
    >
>;

int main()
{
    MultiIndexOrderContainer c;

    // Inserting some orders
    c.insert(std::make_shared<OrderType>(Way::BUY, 10, 15, 0));
    c.insert(std::make_shared<OrderType>(Way::BUY, 10, 14, 1));
    c.insert(std::make_shared<OrderType>(Way::BUY, 10, 13, 2));
    c.insert(std::make_shared<OrderType>(Way::SELL, 10, 16, 3));
    c.insert(std::make_shared<OrderType>(Way::SELL, 10, 17, 4));
    c.insert(std::make_shared<OrderType>(Way::SELL, 10, 18, 5));

    return 0;
}

我想迭代:

  1. 关于按时间戳排序的特定价格的采购订单
  2. 卖出订单中最便宜的订单价格
  3. 采购订单中最昂贵的订单价格

我怎样才能做到这一点?

【问题讨论】:

  • 您可以将multi_index容器的排序索引与boost::filter_iterator一起使用。
  • @Jarod42,这听起来可能是个好主意,但时间复杂度是线性的。我正在使用多索引来提高性能。

标签: c++ performance c++11 boost-multi-index


【解决方案1】:

Boost.MultiIndex 不提供任何特殊机制来混合由不同索引引起的顺序:使用您建议的结构,您基本上可以查询第一个参数,然后对返回的范围进行线性扫描。

另一方面,如果您的查询始终采用 (attr1, attr2, attr3) 形式,您可以使用composite keys 加快查询速度。在您的特定情况下,您可以使用复合键 (way_,price_,timestamp_) 进行三个查询

Live On Coliru

#include <memory>
#include <iostream>

#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/composite_key.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/member.hpp>

using namespace ::boost;
using namespace ::boost::multi_index;

enum class Way
{
    UNDEFINED,
    BUY,
    SELL
};

template <typename QuantityType, typename PriceType>
struct GenericOrder
{
    explicit GenericOrder(const Way way, const QuantityType& quantity, const PriceType& price, const long long& timestamp)
        : way_(way), quantity_(quantity), price_(price), timestamp_(timestamp)
    {
    }

    ~GenericOrder() = default;
    GenericOrder(const GenericOrder&) = delete;
    GenericOrder& operator=(const GenericOrder&) = delete;

    Way way_;
    QuantityType quantity_;
    PriceType price_;
    long long timestamp_ = -1;
};

template <typename QuantityType, typename PriceType>
std::ostream& operator<<(std::ostream& os,const GenericOrder<QuantityType,PriceType>& o)
{
    switch(o.way_){
        case Way::UNDEFINED: os<<"UNDEFINED, ";break;
        case Way::BUY: os<<"BUY, ";break;
        case Way::SELL: os<<"SELL, ";break;
    }
    return os<<o.price_<<", "<<o.timestamp_<<"\n";
}

// Aliases
using QuantityType = int;
using PriceType = int;
using OrderType = GenericOrder<QuantityType, PriceType>;
using PointerType = std::shared_ptr<OrderType>;

struct way {};
struct timestamp {};
struct price {};

using MultiIndexOrderContainer = multi_index_container<PointerType,
    indexed_by<
        ordered_non_unique<
            composite_key<
                OrderType,
                member<OrderType, decltype(OrderType::way_), &OrderType::way_ >,
                member<OrderType, decltype(OrderType::price_), &OrderType::price_>,
                member<OrderType, decltype(OrderType::timestamp_), &OrderType::timestamp_ >
            >
        >
    >
>;

int main()
{
    MultiIndexOrderContainer c;

    // Inserting some orders
    c.insert(std::make_shared<OrderType>(Way::BUY, 10, 15, 0));
    c.insert(std::make_shared<OrderType>(Way::BUY, 10, 14, 1));
    c.insert(std::make_shared<OrderType>(Way::BUY, 10, 13, 2));
    c.insert(std::make_shared<OrderType>(Way::BUY, 10, 15, 1));
    c.insert(std::make_shared<OrderType>(Way::SELL, 10, 16, 3));
    c.insert(std::make_shared<OrderType>(Way::SELL, 10, 17, 4));
    c.insert(std::make_shared<OrderType>(Way::SELL, 10, 18, 5));

    std::cout<<"Buying orders for 15, sorted by timestamp\n";
    auto p=c.equal_range(std::make_tuple(Way::BUY,15));
    while(p.first!=p.second)std::cout<<**p.first++;

    std::cout<<"Cheapest selling order\n";
    std::cout<<**c.lower_bound(Way::SELL);

    std::cout<<"Costliest buying order\n";
    std::cout<<**--c.upper_bound(Way::BUY);

return 0;
}

【讨论】:

  • 我正在构建包装器来使用这些函数,并且我正在研究复合键之上的散列索引。你觉得可以兼容吗?
  • 当使用带有散列索引的复合键时,您有一个限制,即不支持部分查询。例如,如果您的复合键为 (attr1,attr2,attr3),您不能查询 (attr1,attr2)(可以使用有序索引),只能查询整个元组。
  • 哦,好吧,要利用复合键和散列索引,唯一的方法是复制索引(一个复合,一个散列)?
  • 这完全取决于您的查询模式。如果您只查找 (attr1,attr2) 和 (attr1,attr2,attr3) 两个散列索引,一个使用 Composite_key(attr1,attr2),另一个使用 Composite_key(attr1,attr2),就可以了。当然,当模式太多时,不建议添加越来越多的具体指标……与往常一样,衡量并做出相应的决定。
猜你喜欢
  • 1970-01-01
  • 2010-12-21
  • 1970-01-01
  • 2010-12-14
  • 1970-01-01
  • 2018-06-14
  • 1970-01-01
  • 2021-05-05
  • 1970-01-01
相关资源
最近更新 更多