Search code examples
c#.netfilteringravendb

RavenDb: Why filtering while string == null filters too much?


I want to filter the EquipmentEntity list by Type if it is specified (different from null). The type is a nullable string.

Request:

public class GetEquipmentsQuery : IQuery<List<EquipmentDto>> {
    public string? Name { get; set; }
    public double? Price { get; set; }
    public string? Type { get; set; }

}

Filtering:

var equipments = await session
.Query<EquipmentEntity>()
.Where(a => (request.Type == null || a.Type == request.Type))
.ToListAsync(cancellationToken);

If the Type property equals null, equipments is an empty list. If the Type property has a value and there is an EquipmentEntity whose Type property has that value, it is included in the list of returned elements.

I have a problem with that condition:

var equipments = await session
.Query<EquipmentEntity>()
.Where(a => request.Type == null)
.ToListAsync(cancellationToken);

I tested how the filtering works with a simplified condition. Although request.Type == null is true, them for some reason equipments is empty.

I do not have this problem with very similar filtering:

var equipments = await session
.Query<EquipmentEntity>()
.Where(a => (request.Price == null || a.Price <= request.Price))
.ToListAsync(cancellationToken);

In this case, if Price property equals null it does not affect the filtering and receives a proper list. The only difference I notice here is that Price property is a nullable double and Type property is a nullable string.

How can I make Where so that it filters correctly when the given Type property from the request is null?


Solution

  • For now, this is working for me:

            using var session = _context.Store.OpenAsyncSession();
            
            var query = session.Query<EquipmentEntity>();
            if (request.Name != null) {
                query = query.Search(a => a.Name, $"*{request.Name}*");
            }
    
            if (request.Price != null) {
                query = query.Where(a => a.Price <= request.Price);
            }
            
            if (request.Type != null) {
                query = query.Where(a => a.Type == request.Type);
            }
    
            var equipments= await query.ToListAsync(cancellationToken);
            
            return _mapper.Map<List<EquipmentDto>>(equipments);
    

    I only add further filters when I know that a request field is different from null. This avoids the problem of filter Where(a => (request.Type == null || a.Type == request.Type)) because aligning to a specific value filters the list as expected.

    However, this is a workaround and I would like to understand why previous approach return empty list.