For anything but the MemoryStore, there is considerable overhead in each request for information from an underlying database. With the MySQL store, for instance, a call to Select makes a SQL SELECT query on the database. There is overhead in constructing, transmitting across processes, and parsing the query, and then the response. This makes repeated calls to Select (the method) much slower than they should be if they could be combined into a single SQL SELECT.
SemWeb has an advanced API call, an overload of Select, taking a SelectFilter argument, which allows the caller to query for statements matching a more complex filter than the simple form of Select. In the simple form, the subject, predicate, object, and meta can be either 1) specified or 2) a wildcard. In the more complex API, there is a third option, which is specifying a range of possible values. Schematically, these three calls to select:
Select(X, null, null) Select(Y, null, null) Select(Z, null, null)
can be replaced with a single call like this:
Select( { X, Y, Z}, null, null);
Further, these permutations can be condensed into a single call:
Select(X, A, null) Select(Y, A, null) Select(Z, A, null) Select(X, B, null) Select(Y, B, null) Select(Z, B, null) Select(X, C, null) Select(Y, C, null) Select(Z, C, null) Select( { X, Y, Z}, { A, B, C}, null);
The statements returned from the complex Select are those that match any of the provided resources.
The actual syntax uses arrays of entities or, for objects, resources. As an example, one use case of this is to fetch the foaf:name of many entities in one call.
SelectFilter filter = new SelectFilter(); // for now all wildcards filter.Subjects = new Entity[] { X, Y, Z }; filter.Predicates = new Entity[] { foaf_name }; // filter.Objects, filter.Metas are left as wildcards store.Select(filter, sink);
The sink receives all statements whose subject is X, Y, or Z, and whose predicate is foaf_name.