I have the following class and I need to index employee's hobbies.
class Employee {
...
std::vector<std::string> hobbies;
}
The suggested way to do it is to create a flat structure:
struct EmployeeWithHobby {
Employee employee;
std::string hobby;
};
And then index by this field:
typedef boost::multi_index::multi_index_container<
EmployeeWithHobby,
boost::multi_index::indexed_by<
boost::multi_index::hashed_non_unique<
boost::multi_index::tag<ByHobby>,
boost::multi_index::member<
EmployeeWithHobby, std::string,
&EmployeeWithHobby::hobby>>>> index;
This works great so far. But what if I need to index another vector. Let's say employee has different skills:
class Employee {
...
std::vector<std::string> hobbies;
std::vector<std::string> skills;
}
How would I index both of these fields? Would I create a separate struct and a separate index?
struct EmployeeWithSkill {
Employee employee;
std::string skill;
};
typedef boost::multi_index::multi_index_container<
EmployeeWithHobby, ...
Or should I add a field to the existing struct?
struct EmployeeWithHobbyAndSkill {
Employee employee;
std::string hobby;
std::string skill;
};
That would require O(N*M) insertions because I would have to iterate both hobbies and skills. If there is another vector, it quickly becomes unmanageable...
Or can I use std::optional
to avoid O(N*M) and turns into O(N+M) entries?
struct EmployeeWithHobbyAndSkill {
Employee employee;
std::optional<std::string> hobby;
std::optional<std::string> skill;
};
Optimizing The Base Problem
You could use pre-indexed hobbies/skills (they will likely form a slowly growing static set).
A very minimal example:
Live On Coliru
Printing
Enter Multi Index
With Multi Index, it could be that you hope to actually lookup all the entries that match a given skill/hobby. You can achieve it with a custom comparison predicate and many indices, but it will not be very flexible.
Instead, you may want to have several indexes over the same table:
Live On Coliru
Printing
TL;DR Summary
Abstract your database to optimize for your usage patterns. If you many-to-many relations, this invariably means either de-normalizing data or using multiple relation tables in normal-form.
Of course you will give thought to guaranteeing the constraints, which is why you need to have a strict interface on your abstraction, so it cannot be used "wrong".
Note that you might well be able to write your bespoke query directly on a
And it might suffice for your needs.