# Read Operations

# Find Operations

You can search entities in a repository using find() method. There are several overloaded version of find() method using a filter or find options or both. You can also search an entity using it's id.

# Filters

Nitrite uses filters to find entities in a repository. A filter is a simple expression which evaluates to true or false. More information about filters can be found here.

# Find All Entities

You can find all entities in a repository by calling find(). It returns a Cursor object.

Cursor<Product> cursor = productRepository.find();

# Finding an Entity Using Id

You can find an entity using it's id by calling getById(). It takes an id as input parameter. It returns an entity if the entity is found. Otherwise, it returns null.

Product product = productRepository.getById(new ProductId(1));

# Finding an Entity Using a Filter

You can find an entity using a filter. It takes a Filter object as input parameter. It returns a Cursor object.

If there is an index on the field specified in the filter, this operation will use the index to find the entity. Otherwise, it will scan the entire repository to find the entity.

Cursor<Product> cursor = productRepository.find(where("productName").eq("Apple iPhone 6"));

# Finding an Entity Using a Filter and Options

You can find an entity using a filter and options. It takes a Filter object as the first input parameter. It takes a FindOptions object as the second input parameter. It returns a Cursor object.

# FindOptions

More information about FindOptions can be found here.

# Cursor

Cursor represents a result set of a find operation. It provides methods to iterate over the result of a find operation and retrieve the entities. It also provides methods like projection, join etc. to get the desired result.

# Iterating over Entities

The Cursor extends Iterable interface. So, you can iterate over the entities using for-each loop.

Cursor<Product> cursor = productRepository.find();

for (Product product : cursor) {
    // do something with the product
}

# Getting the Entities

You can get the entities from the cursor at once using toList() and toSet() method. It returns a List and Set of entities respectively.

Cursor<Product> cursor = productRepository.find();

List<Product> products = cursor.toList();
Set<Product> productSet = cursor.toSet();

# Getting the First Entity

You can get the first entity from the cursor using firstOrNull() method. It returns the first entity if the cursor is not empty. Otherwise, it returns null.

Cursor<Product> cursor = productRepository.find();

Product product = cursor.firstOrNull();

# Getting the Size of the Cursor

You can get the size of the cursor using size() method. It returns the number of entities in the cursor.

Cursor<Product> cursor = productRepository.find();

long size = cursor.size();

# Projection

You can project the cursor using project() method. It takes another entity type as input parameter. It returns a Cursor object of the projected entity.

The projected entity must contain only the fields that needs to be projected.

Let's say you have an entity like this:

public class User {
    private String firstName;
    private String lastName;
    private Address address;
}

public class Address {
    private String street;
    private String city;
}

And you want to project only lastName and address.street fields. Then you can define a new entity like this:

public class UserProjection {
    private String lastName;
    private StreetAddress address;
}

public class StreetAddress {
    private String street;
}

And then you can project the cursor like this:

Cursor<User> cursor = userRepository.find(where("firstName").eq("John"));

RecordStream<UserProjection> projectedStream = cursor.project(UserProjection.class);

# Join

You can join two cursors using join() method. It takes another cursor as the first input parameter. It takes a Lookup as the second input parameter and type of the join as the third input parameter. It returns a RecordStream object.

The join operation is similar to SQL left outer join operation. It takes two cursors and a lookup object. The lookup object contains the join condition.

Let's say you have two entities like this:

public class User {
    private String userId;
    private String firstName;
    private String lastName;
}

public class Order {
    private String orderId;
    private String userId;
    private String productName;
}

And you want to join these two entities using userId field. Then you can define a new entity like this:

public class UserOrder {
    private String userId;
    private String firstName;
    private String lastName;
    private List<Order> orders;
}

And then you can join the cursors like this:

Cursor<User> userCursor = userRepository.find();
Cursor<Order> orderCursor = orderRepository.find();

Lookup lookup = new Lookup();
lookup.setLocalField("userId");
lookup.setForeignField("userId");
lookup.setTargetField("orders");

RecordStream<UserOrder> joinedStream = userCursor.join(orderCursor, lookup, UserOrder.class);

# FindPlan

You can get the FindPlan of a cursor using getFindPlan() method. It returns a FindPlan object.

More information about FindPlan can be found here.

Cursor<Product> cursor = productRepository.find(where("productName").eq("Apple iPhone 6"));

FindPlan findPlan = cursor.getFindPlan();