本博客http://blog.csdn.net/livelylittlefish 贴 出作 者(三二一@小鱼)相关研究、学习内容所做的笔记,欢迎广大朋友指正!
1. 引子
在 实例 (1) 、实例 ( 续 2) 、实例 ( 续 3) 、实例 ( 续 4) 、实例 ( 续 5) 这个系列的例子中,我们演示的是对多个索引的整体查询,即对元组 r=(x,y,z,a,b) ,其中 为索引, 为一个数据对,我们在对集合 R={r} 这个多索引的数据表查询时,直接给定索引 。
如果我们想查询 x 索引值为 x0 的所有数据,或者查询 x 、 y 索引值分别为 x0 、 y0 的所有数据,即这种组合查询,该如何查?上述系列的例子能否查得到?如果查不到,该如何调整 MyContainer_T 的结构?
有兴趣的读者可以自行实验,上述系列的例子不支持这种组合查询。
那么组合查询如何改写 MyContainer_T 的结构?这就是本系列要讲的 组合查询 。
关于组合查询的讲解,可以参考后续的文章。
2. 修改 MyContainer_T 的结构
struct x_key :composite_key <
MyTest,
BOOST_MULTI_INDEX_MEMBER (MyTest, int, x)
>{};
struct xy_key :composite_key <
MyTest,
BOOST_MULTI_INDEX_MEMBER (MyTest, int, x),
BOOST_MULTI_INDEX_MEMBER (MyTest, int, y)
>{};
struct xyz_key :composite_key <
MyTest,
BOOST_MULTI_INDEX_MEMBER (MyTest, int, x),
BOOST_MULTI_INDEX_MEMBER (MyTest, int, y),
BOOST_MULTI_INDEX_MEMBER (MyTest, int, z)
>{};
struct MyIndex_X_Tag {};
struct MyIndex_XY_Tag {};
struct MyIndex_XYZ_Tag {};
typedef multi_index_container <
MyTest*,
indexed_by<
ordered_non_unique <tag< MyIndex_X_Tag >, x_key , composite_key_result_less <x_key::result_type> >,
ordered_non_unique <tag<MyIndex_XY_Tag >, xy_key ,composite_key_result_less <xy_key::result_type> >,
ordered_unique <tag< MyIndex_XYZ_Tag >, xyz_key , composite_key_result_less <xyz_key::result_type> >
>
>MyContainer_T ;
// 分别定义第 1 、 2 、 3 种组合查询对应的 contaniner 的类型
typedef nth_index<MyContainer_T , 0>::type MyContainer_X_T ;
typedef nth_index<MyContainer_T , 1>::type MyContainer_XY_T ;
typedef nth_index<MyContainer_T , 2>::type MyContainer_XYZ_T ;
3. 代码及运行结果
multiindexcontainer11.cpp
/** * boost multi index container test * platform: win32, visual studio 2005/2010; Linux, gcc4.1.2 */ #include <iostream> #include <boost/multi_index_container.hpp> #include <boost/multi_index/composite_key.hpp> #include <boost/multi_index/member.hpp> #include <boost/multi_index/ordered_index.hpp> using namespace std; using namespace boost::multi_index; using boost::multi_index_container; //define data to be indexed typedef struct { int a; int b; }MyData; //define object to be indexed class MyTest { public: int x; int y; int z; MyData myData; public: MyTest(int x_, int y_, int z_, int a, int b):x(x_), y(y_), z(z_) { myData.a = a; myData.b = b; } ~MyTest() { cout << "(" << x << ", " << y << ", " << z << ") - "; cout << "(" << myData.a << ", " << myData.b << "), destructed" << endl; } void print(char* prompt) const { cout << "(" << x << ", " << y << ", " << z << ") - "; cout << "(" << myData.a << ", " << myData.b << ")" << prompt << endl; } friend std::ostream& operator<<(std::ostream& os, const MyTest* mytest) { mytest->print(""); return os; } private: MyTest(const MyTest&); MyTest& operator=(const MyTest&); }; struct x_key:composite_key< MyTest, BOOST_MULTI_INDEX_MEMBER(MyTest, int, x) >{}; struct xy_key:composite_key< MyTest, BOOST_MULTI_INDEX_MEMBER(MyTest, int, x), BOOST_MULTI_INDEX_MEMBER(MyTest, int, y) >{}; struct xyz_key:composite_key< MyTest, BOOST_MULTI_INDEX_MEMBER(MyTest, int, x), BOOST_MULTI_INDEX_MEMBER(MyTest, int, y), BOOST_MULTI_INDEX_MEMBER(MyTest, int, z) >{}; struct MyIndex_X_Tag{}; struct MyIndex_XY_Tag{}; struct MyIndex_XYZ_Tag{}; typedef multi_index_container< MyTest*, indexed_by< ordered_non_unique<tag<MyIndex_X_Tag>, x_key, composite_key_result_less<x_key::result_type> >, ordered_non_unique<tag<MyIndex_XY_Tag>, xy_key, composite_key_result_less<xy_key::result_type> >, ordered_unique<tag<MyIndex_XYZ_Tag>, xyz_key, composite_key_result_less<xyz_key::result_type> > > >MyContainer_T; typedef nth_index<MyContainer_T, 0>::type MyContainer_X_T; typedef nth_index<MyContainer_T, 1>::type MyContainer_XY_T; typedef nth_index<MyContainer_T, 2>::type MyContainer_XYZ_T; typedef MyContainer_T::index<MyIndex_X_Tag>::type MyContainerIndex_X_T; typedef MyContainer_T::index<MyIndex_X_Tag>::type::iterator MyContainerIterator_X_T; typedef std::pair<MyContainerIterator_X_T, bool> MyContainerPair_X_T; typedef MyContainer_T::index<MyIndex_XY_Tag>::type MyContainerIndex_XY_T; typedef MyContainer_T::index<MyIndex_XY_Tag>::type::iterator MyContainerIterator_XY_T; typedef std::pair<MyContainerIterator_XY_T, bool> MyContainerPair_XY_T; typedef MyContainer_T::index<MyIndex_XYZ_Tag>::type MyContainerIndex_XYZ_T; typedef MyContainer_T::index<MyIndex_XYZ_Tag>::type::iterator MyContainerIterator_XYZ_T; typedef std::pair<MyContainerIterator_XYZ_T, bool> MyContainerPair_XYZ_T; MyContainer_T mycontainer; MyContainer_X_T& mycontainerx = mycontainer; MyContainer_XY_T& mycontainerxy = get<1>(mycontainer); MyContainer_XYZ_T& mycontainerxyz = get<2>(mycontainer); void query_container(int x) { MyContainerIterator_X_T it0, it1; boost::tie(it0, it1) = mycontainerx.equal_range(boost::make_tuple(x)); if (*it0 == *it1) { cout << "("<<x<<") - not found" << endl; return; } while (it0 != it1) { (*it0)->print(", found"); ++it0; } } void query_container(int x, int y) { MyContainerIterator_XY_T it0, it1; boost::tie(it0, it1) = mycontainerxy.equal_range(boost::make_tuple(x, y)); if (*it0 == *it1) { cout << "("<<x<<", "<<y<<") - not found" << endl; return; } while (it0 != it1) { (*it0)->print(", found"); ++it0; } } void query_container(int x, int y, int z) { MyContainerIterator_XYZ_T it0, it1; boost::tie(it0, it1) = mycontainerxyz.equal_range(boost::make_tuple(x, y, z)); if (*it0 == *it1) { cout << "("<<x<<", "<<y<<", "<<z<<") - not found" << endl; return; } while (it0 != it1) { (*it0)->print(", found"); ++it0; } } template<typename Tag, typename MultiIndexContainer> void print_container(const MultiIndexContainer& container) { //obtain a reference to the index tagged by Tag const typename boost::multi_index::index<MultiIndexContainer, Tag>::type& indexSet = get<Tag>(container); typedef typename MultiIndexContainer::value_type value_type; //dump the elements of the index to cout std::copy(indexSet.begin(), indexSet.end(), std::ostream_iterator<value_type>(cout)); } template<typename MultiIndexContainer> void free_container(MultiIndexContainer& container) { typedef typename MultiIndexContainer::value_type value_type; while (!container.empty()) { typename MultiIndexContainer::iterator iter = container.begin(); if (NULL == (*iter)) { container.erase(iter); continue; } value_type pobj = *iter; container.erase(iter); delete pobj; } } void test1() { MyTest *a = new MyTest(1,1,1,10,100); mycontainer.insert(a); MyTest *b = new MyTest(1,1,2,20,200); mycontainer.insert(b); MyTest *c = new MyTest(1,1,3,30,300); mycontainer.insert(c); } void test2() { MyTest *a = new MyTest(1,2,1,40,400); mycontainer.insert(a); MyTest *b = new MyTest(1,2,2,50,500); mycontainer.insert(b); MyTest *c = new MyTest(1,2,3,60,600); mycontainer.insert(c); } void test3() { MyTest *a = new MyTest(1,3,1,70,700); mycontainer.insert(a); MyTest *b = new MyTest(1,3,2,80,800); mycontainer.insert(b); MyTest *c = new MyTest(1,3,3,90,900); mycontainer.insert(c); } void test4() { MyTest *a = new MyTest(2,1,1,110,1000); mycontainer.insert(a); MyTest *b = new MyTest(2,1,2,220,2000); mycontainer.insert(b); MyTest *c = new MyTest(2,1,3,330,3000); mycontainer.insert(c); } void test5() { MyTest *a = new MyTest(2,2,1,440,4000); mycontainer.insert(a); MyTest *b = new MyTest(2,2,2,550,5000); mycontainer.insert(b); MyTest *c = new MyTest(2,2,3,660,6000); mycontainer.insert(c); } void test6() { MyTest *a = new MyTest(2,3,1,770,7000); mycontainer.insert(a); MyTest *b = new MyTest(2,3,2,880,8000); mycontainer.insert(b); MyTest *c = new MyTest(2,3,3,990,9000); mycontainer.insert(c); } void query_test1() { query_container(1); cout<<endl; query_container(2); cout<<endl; query_container(3); } void query_test2() { query_container(1, 1); query_container(1, 2); query_container(1, 3); query_container(1, 4); cout<<endl; query_container(2, 1); query_container(2, 2); query_container(2, 3); query_container(2, 4); } void query_test3() { query_container(1, 1, 1); query_container(1, 1, 2); query_container(1, 1, 3); query_container(1, 2, 1); query_container(1, 2, 2); query_container(1, 2, 3); query_container(1, 3, 1); query_container(1, 3, 2); query_container(1, 3, 3); cout<<endl; query_container(2, 1, 1); query_container(2, 1, 2); query_container(2, 1, 3); query_container(2, 2, 1); query_container(2, 2, 2); query_container(2, 2, 3); query_container(2, 3, 1); query_container(2, 3, 2); query_container(2, 3, 3); cout<<endl; query_container(2, 3, 4); query_container(3, 3, 3); } void query_test() { query_test1(); cout<<endl; query_test2(); cout<<endl; query_test3(); } int main() { test2(); test4(); test6(); test1(); test3(); test5(); //print_container<MyIndex_X_Tag>(mycontainer); //cout<<endl; //print_container<MyIndex_XY_Tag>(mycontainer); //cout<<endl; print_container<MyIndex_XYZ_Tag>(mycontainer); cout<<endl; query_test(); cout<<endl; free_container(mycontainer); return 0; }
运行结果如下:
(1, 1, 1) - (10, 100)
(1, 1, 2) - (20, 200)
(1, 1, 3) - (30, 300)
(1, 2, 1) - (40, 400)
(1, 2, 2) - (50, 500)
(1, 2, 3) - (60, 600)
(1, 3, 1) - (70, 700)
(1, 3, 2) - (80, 800)
(1, 3, 3) - (90, 900)
(2, 1, 1) - (110, 1000)
(2, 1, 2) - (220, 2000)
(2, 1, 3) - (330, 3000)
(2, 2, 1) - (440, 4000)
(2, 2, 2) - (550, 5000)
(2, 2, 3) - (660, 6000)
(2, 3, 1) - (770, 7000)
(2, 3, 2) - (880, 8000)
(2, 3, 3) - (990, 9000)
// 查询索引 x=1 的所有数据
(1, 2, 1) - (40, 400), found
(1, 2, 2) - (50, 500), found
(1, 2, 3) - (60, 600), found
(1, 1, 1) - (10, 100), found
(1, 1, 2) - (20, 200), found
(1, 1, 3) - (30, 300), found
(1, 3, 1) - (70, 700), found
(1, 3, 2) - (80, 800), found
(1, 3, 3) - (90, 900), found
// 查询索引 x=2 的所有数据
(2, 1, 1) - (110, 1000), found
(2, 1, 2) - (220, 2000), found
(2, 1, 3) - (330, 3000), found
(2, 3, 1) - (770, 7000), found
(2, 3, 2) - (880, 8000), found
(2, 3, 3) - (990, 9000), found
(2, 2, 1) - (440, 4000), found
(2, 2, 2) - (550, 5000), found
(2, 2, 3) - (660, 6000), found
// 查询索引 x=3 的所有数据
(3) - not found
// 查询索引 的所有数据
(1, 1, 1) - (10, 100), found
(1, 1, 2) - (20, 200), found
(1, 1, 3) - (30, 300), found
// 查询索引 的所有数据
(1, 2, 1) - (40, 400), found
(1, 2, 2) - (50, 500), found
(1, 2, 3) - (60, 600), found
// 查询索引 的所有数据
(1, 3, 1) - (70, 700), found
(1, 3, 2) - (80, 800), found
(1, 3, 3) - (90, 900), found
// 查询索引 的所有数据
(1, 4) - not found
// 查询索引 的所有数据
(2, 1, 1) - (110, 1000), found
(2, 1, 2) - (220, 2000), found
(2, 1, 3) - (330, 3000), found
// 查询索引 的所有数据
(2, 2, 1) - (440, 4000), found
(2, 2, 2) - (550, 5000), found
(2, 2, 3) - (660, 6000), found
// 查询索引 的所有数据
(2, 3, 1) - (770, 7000), found
(2, 3, 2) - (880, 8000), found
(2, 3, 3) - (990, 9000), found
// 查询索引 的所有数据
(2, 4) - not found
// 查询索引 ~ 的所有数据
(1, 1, 1) - (10, 100), found
(1, 1, 2) - (20, 200), found
(1, 1, 3) - (30, 300), found
(1, 2, 1) - (40, 400), found
(1, 2, 2) - (50, 500), found
(1, 2, 3) - (60, 600), found
(1, 3, 1) - (70, 700), found
(1, 3, 2) - (80, 800), found
(1, 3, 3) - (90, 900), found
(2, 1, 1) - (110, 1000), found
(2, 1, 2) - (220, 2000), found
(2, 1, 3) - (330, 3000), found
(2, 2, 1) - (440, 4000), found
(2, 2, 2) - (550, 5000), found
(2, 2, 3) - (660, 6000), found
(2, 3, 1) - (770, 7000), found
(2, 3, 2) - (880, 8000), found
(2, 3, 3) - (990, 9000), found
// 查询索引 等的所有数据
(2, 3, 4) - not found
(3, 3, 3) - not found
// 释放 container
(1, 2, 1) - (40, 400), destructed
(1, 2, 2) - (50, 500), destructed
(1, 2, 3) - (60, 600), destructed
(1, 1, 1) - (10, 100), destructed
(1, 1, 2) - (20, 200), destructed
(1, 1, 3) - (30, 300), destructed
(1, 3, 1) - (70, 700), destructed
(1, 3, 2) - (80, 800), destructed
(1, 3, 3) - (90, 900), destructed
(2, 1, 1) - (110, 1000), destructed
(2, 1, 2) - (220, 2000), destructed
(2, 1, 3) - (330, 3000), destructed
(2, 3, 1) - (770, 7000), destructed
(2, 3, 2) - (880, 8000), destructed
(2, 3, 3) - (990, 9000), destructed
(2, 2, 1) - (440, 4000), destructed
(2, 2, 2) - (550, 5000), destructed
(2, 2, 3) - (660, 6000), destructed
本系列的所有例子均以上述数据为例。
注释为笔者加入。
Reference
./l ibs/multi_index/doc/index.html
./ libs/multi_index/doc/tutorial/key_extraction.html#composite_keys
./ libs/multi_index/doc/examples.html#example7
其中, . 为 Boost 安装路径。
Technorati 标签: Boost , multi_index , multi_index_container