3.5.8. Filtering data on a Topic
3.5.8.1. Creating a ContentFilteredTopic
A ContentFilteredTopic always belongs to a DomainParticipant.
Creation of a ContentFilteredTopic is done with the create_contentfilteredtopic()
member
function on the DomainParticipant
instance, that acts as a factory for the ContentFilteredTopic
.
Mandatory arguments are:
A string with the name that identifies the ContentFilteredTopic.
The related
Topic
being filtered.A string with the filter expression indicating the conditions for a sample to be returned.
A list of strings with the value of the parameters present on the filter expression.
Note
The number of parameter values cannot exceed the maximum set by the
expression_parameters
QoS configuration.
The default (and absolute) maximum allowed as set by the OMG DDS Standard is 100.
Optional arguments are:
A string with the name of the filter class to use for the filter creation. This allows the user to create filters different from the standard SQL like one (please refer to Using custom filters). Defaults to
FASTDDS_SQLFILTER_NAME
(DDSSQL
).
Important
Setting an empty string as filter expression results in the disabling of the filtering. This can be used to enable/disable the DataReader filtering capabilities at any given time by simply updating the filter expression.
create_contentfilteredtopic()
will return a null pointer if there was an error during the
operation, e.g. if the related Topic belongs to a different DomainParticipant, a Topic with the same name already
exists, syntax errors on the filter expression, or missing parameter values.
It is advisable to check that the returned value is a valid pointer.
Note
Different filter classes may impose different requirements on the related Topic, the expression, or the parameters. The default filter class, in particular, requires that a TypeObject for the related Topic’s type has been registered. When using fastddsgen the TypeObject registration code is generated by default.
// Create a DomainParticipant in the desired domain
DomainParticipant* participant =
DomainParticipantFactory::get_instance()->create_participant(0, PARTICIPANT_QOS_DEFAULT);
if (nullptr == participant)
{
// Error
return;
}
// Create the Topic.
/* IDL
*
* struct HelloWorld
* {
* long index;
* string message;
* }
*
*/
Topic* topic =
participant->create_topic("HelloWorldTopic", "HelloWorld", TOPIC_QOS_DEFAULT);
if (nullptr == topic)
{
// Error
return;
}
// Create a ContentFilteredTopic using an expression with no parameters
std::string expression = "message like 'Hello*'";
std::vector<std::string> parameters;
ContentFilteredTopic* filter_topic =
participant->create_contentfilteredtopic("HelloWorldFilteredTopic1", topic, expression, parameters);
if (nullptr == filter_topic)
{
// Error
return;
}
// Create a ContentFilteredTopic using an expression with parameters
expression = "message like %0 or index > %1";
parameters.push_back("'*world*'");
parameters.push_back("20");
ContentFilteredTopic* filter_topic_with_parameters =
participant->create_contentfilteredtopic("HelloWorldFilteredTopic2", topic, expression, parameters);
if (nullptr == filter_topic_with_parameters)
{
// Error
return;
}
// The ContentFilteredTopic instances can then be used to create DataReader objects.
Subscriber* subscriber =
participant->create_subscriber(SUBSCRIBER_QOS_DEFAULT);
if (nullptr == subscriber)
{
// Error
return;
}
DataReader* reader_on_filter = subscriber->create_datareader(filter_topic, DATAREADER_QOS_DEFAULT);
if (nullptr == reader_on_filter)
{
// Error
return;
}
DataReader* reader_on_filter_with_parameters =
subscriber->create_datareader(filter_topic_with_parameters, DATAREADER_QOS_DEFAULT);
if (nullptr == reader_on_filter_with_parameters)
{
// Error
return;
}
3.5.8.2. Updating the filter expression and parameters
A ContentFilteredTopic provides several member functions for the management of the filter expression and the expression parameters:
The filter expression can be retrieved with the
get_filter_expression()
member function.The expression parameters can be retrieved with the
get_expression_parameters()
member function.The expression parameters can be modified using the
set_expression_parameters()
member function. The same constraints as when creating a ContentFilteredTopic apply.The filter expression can be modified along with the expression parameters using the
set_filter_expression()
member function.
// This lambda prints all the information of a ContentFilteredTopic
auto print_filter_info = [](
const ContentFilteredTopic* filter_topic)
{
std::cout << "ContentFilteredTopic info for '" << filter_topic->get_name() << "':" << std::endl;
std::cout << " - Related Topic: " << filter_topic->get_related_topic()->get_name() << std::endl;
std::cout << " - Expression: " << filter_topic->get_filter_expression() << std::endl;
std::cout << " - Parameters:" << std::endl;
std::vector<std::string> parameters;
filter_topic->get_expression_parameters(parameters);
size_t i = 0;
for (const std::string& parameter : parameters)
{
std::cout << " " << i++ << ": " << parameter << std::endl;
}
};
// Create a DomainParticipant in the desired domain
DomainParticipant* participant =
DomainParticipantFactory::get_instance()->create_participant(0, PARTICIPANT_QOS_DEFAULT);
if (nullptr == participant)
{
// Error
return;
}
// Create a Topic
/* IDL
*
* struct HelloWorld
* {
* long index;
* string message;
* }
*
*/
Topic* topic =
participant->create_topic("HelloWorldTopic", "HelloWorldTopic", TOPIC_QOS_DEFAULT);
if (nullptr == topic)
{
// Error
return;
}
// Create a ContentFilteredTopic
ContentFilteredTopic* filter_topic =
participant->create_contentfilteredtopic("HelloWorldFilteredTopic", topic, "index > 10", {});
if (nullptr == filter_topic)
{
// Error
return;
}
// Print the information
print_filter_info(filter_topic);
// Use the ContentFilteredTopic on DataReader objects.
// (...)
// Update the expression
if (RETCODE_OK !=
filter_topic->set_filter_expression("message like %0 or index > %1", {"'Hello*'", "15"}))
{
// Error
return;
}
// Print the updated information
print_filter_info(filter_topic);
// Update the parameters
if (RETCODE_OK !=
filter_topic->set_expression_parameters({"'*world*'", "222"}))
{
// Error
return;
}
// Print the updated information
print_filter_info(filter_topic);
3.5.8.3. Deleting a ContentFilteredTopic
A ContentFilteredTopic can be deleted with the delete_contentfilteredtopic()
member function
on the DomainParticipant instance where the ContentFilteredTopic was created.
// Create a DomainParticipant in the desired domain
DomainParticipant* participant =
DomainParticipantFactory::get_instance()->create_participant(0, PARTICIPANT_QOS_DEFAULT);
if (nullptr == participant)
{
// Error
return;
}
// Create a Topic
/* IDL
*
* struct HelloWorld
* {
* long index;
* string message;
* }
*
*/
Topic* topic =
participant->create_topic("HelloWorldTopic", "HelloWorldTopic", TOPIC_QOS_DEFAULT);
if (nullptr == topic)
{
// Error
return;
}
// Create a ContentFilteredTopic
ContentFilteredTopic* filter_topic =
participant->create_contentfilteredtopic("HelloWorldFilteredTopic", topic, "index > 10", {});
if (nullptr == filter_topic)
{
// Error
return;
}
// Use the ContentFilteredTopic on DataReader objects.
// (...)
// Delete the ContentFilteredTopic
if (RETCODE_OK != participant->delete_contentfilteredtopic(filter_topic))
{
// Error
return;
}