findTriples method

List<Triple> findTriples({
  1. RdfSubject? subject,
  2. Iterable<RdfSubject>? subjectIn,
  3. RdfPredicate? predicate,
  4. Iterable<RdfPredicate>? predicateIn,
  5. RdfObject? object,
  6. Iterable<RdfObject>? objectIn,
})

Find all triples matching the given pattern

This method returns triples that match all the specified pattern components. Unlike withoutMatching, this method uses AND logic - all specified components must match. If a pattern component is null, it acts as a wildcard.

Set-based Queries: The *In parameters allow efficient querying for triples that match any value in a set. When multiple values are provided via these parameters, the method returns triples matching ANY of those values (OR logic within the set), while different parameter types still use AND logic.

Performance: When subjectIn is used with indexing enabled, this method leverages the internal index structure for optimal performance, especially beneficial when querying for multiple subjects.

Parameters:

  • subject Optional subject to match (exact match)
  • subjectIn Optional set of subjects - matches triples with ANY of these subjects
  • predicate Optional predicate to match (exact match)
  • predicateIn Optional set of predicates - matches triples with ANY of these predicates
  • object Optional object to match (exact match)
  • objectIn Optional set of objects - matches triples with ANY of these objects

Note: If both subject and subjectIn are provided, they are combined. The same applies to predicate/predicateIn and object/objectIn pairs. Empty sets in *In parameters will match nothing.

Returns: List of matching triples as an unmodifiable collection. The list may be empty if no matching triples exist.

Example:

// Find all statements about John
final johnsTriples = graph.findTriples(subject: john);

// Find all name statements
final nameTriples = graph.findTriples(predicate: name);

// Find John's name specifically
final johnsName = graph.findTriples(subject: john, predicate: name);

// Find statements about John OR Jane (set-based query)
final multipleSubjects = graph.findTriples(subjectIn: [john, jane]);

// Find name OR email properties (set-based query)
final contactInfo = graph.findTriples(predicateIn: [name, email]);

// Combine set-based and exact match filters
final johnOrJaneName = graph.findTriples(
  subjectIn: [john, jane],
  predicate: name,
);

// Complex query with multiple sets
final results = graph.findTriples(
  subjectIn: [john, jane, bob],
  predicateIn: [name, email],
  objectIn: [targetValue1, targetValue2],
);

Implementation

List<Triple> findTriples({
  RdfSubject? subject,
  Iterable<RdfSubject>? subjectIn,
  RdfPredicate? predicate,
  Iterable<RdfPredicate>? predicateIn,
  RdfObject? object,
  Iterable<RdfObject>? objectIn,
}) {
  final subjectSet = (subject != null || subjectIn != null)
      ? {if (subject != null) subject, ...?subjectIn}
      : null;

  final predicateSet = (predicate != null || predicateIn != null)
      ? {if (predicate != null) predicate, ...?predicateIn}
      : null;

  final objectSet = (object != null || objectIn != null)
      ? {if (object != null) object, ...?objectIn}
      : null;

  if (subjectSet != null && _effectiveIndex != null) {
    final index = _effectiveIndex!;
    // If subjectSet is empty, the for loop simply won't run, correctly returning [].
    final List<Triple> results = [];
    for (final s in subjectSet) {
      final subjectMap = index[s];
      if (subjectMap == null) continue;

      final Iterable<Triple> candidates;
      if (predicateSet != null) {
        // If predicateSet is empty, this correctly produces no candidates.
        candidates = predicateSet
            .map((p) => subjectMap[p])
            .nonNulls
            .expand((list) => list);
      } else {
        candidates = subjectMap.values.expand((list) => list);
      }

      if (objectSet != null) {
        // If objectSet is empty, .where() will correctly filter everything out.
        results.addAll(
            candidates.where((triple) => objectSet.contains(triple.object)));
      } else {
        results.addAll(candidates);
      }
    }
    return List.unmodifiable(results);
  }

  return List.unmodifiable(
    _triples.where(
        (triple) => _matches(triple, subjectSet, predicateSet, objectSet)),
  );
}