RavenDB: .In() and .Where() yielding different results - ravendb

I have a field, that's indexed as
Index(x => x.Status, FieldIndexing.Default);
in a collection with a total of 2566 records.
Now when I query like this:
var query = _ravenSession
.Query<MyIndex.ReduceResult, MyIndex>()
.Statistics(out stats);
query = query.Where(x => x.Status != "inactive" && x.Status != "invalid" && x.Status != "sold");
I get a total result count of 2512.
But if I query like this:
query = query.Where(x => !x.Status.In("inactive", "invalid", "sold"));
I get a total result count of 2520. How can this count be different?
I can see, that the first query translates to
{((((-Status:inactive AND Status:*) AND -Status:invalid))
AND -Status:sold)}
and the second one:
{(: AND -#in`<Status>:(inactive , invalid , sold) )}

There is a difference with how this query is processed.
In the first case, you are allowing only results that have a Status, in the second, you are saying everything but those particular values. So if you have values that don't have the status property, that might explain it.

Related

Selection from the table by two parameters

There is a table, where i store information about bookings.
It's a simple one. Has just few attr like: bookingId, personId, date and shouldBeConsidered
I want to retrieve for each person booked from som period of time for last 10 days and then to include property shouldBeConsidered.
For instance there were 100 bookings and 2 of those amount should be taken from db. And also, there can be person who booked 100 booking where is 0 shouldBeConsidered
I've code something like this:
var res = await this.context.Bookings
.Where(x => x.DateTime >= bookingsStartDateTime || x.ShouldBeConsidered)
.GroupBy(x => br.PId)
.Select(x => Dal
{
Id = br.Key,
TotalBookings = x.Count(),
BookingsIssues = x.Count(x => x.ShouldBeConsidered)
})
.ToListAsync();
But, unfortuanlly, it does not work properly. Sometimes, it could take a bit more issues and also count a bit more total.
You will need a bit more clear example with a few record scenarios followed by what you expect to have been returned and what you actually got returned. Your logic is going to give you all bookings where either the booking date >= that start date OR the ShouldBeConsidered flag is true. (regardless of date)
On a hunch I think you probably want to remove that || x.ShouldBeConsidered in that ultimately you'd be interested in the total # of bookings after the start date, and a separate count of the bookings after the start date with that flag set. the statement "and then to include property shouldBeConsidered" seems confusing. All properties of the booking are included/available for querying against:
var res = await this.context.Bookings
.Where(x => x.DateTime >= bookingsStartDateTime)
.GroupBy(x => br.PId)
.Select(x => Dal
{
Id = br.Key,
TotalBookings = x.Count(),
BookingsIssues = x.Count(x => x.ShouldBeConsidered)
}).ToListAsync();

query did not return a unique result: 2 . Issue with Nhibernate Query

I am current having an issue with getting records from database using nhibernate.
My 'publicstring' column is having two values, one with lower case and the other with upper case.
I am trying to fetch one of them depending on what is typed.
Below is my query
private string _publicId;
var _mediaFileShare = this.Session.QueryOver<MediaFileShare>()
.Where(q => q.Publicsting == _publicstring)
.SingleOrDefault();
Answers would be appreciated..
A naive solution is:
var _mediaFileShare = this.Session.QueryOver<MediaFileShare>()
.Where(q => q.PublicString == _publicString)
.List()
.SingleOrDefault(r => string.Compare(r.PublicString, _publicString, StringComparison.Ordinal) == 0);
If you're confident that the query will always return two rows then performance should be very acceptable. Alternatively you could use a dynamic order by, something like:
var query = this.Session.QueryOver<MediaFileShare>()
.Where(q => q.PublicString == _publicString);
query = _publicString == _publicString.ToLower()
? query.OrderBy(q => q.PublicString)
: query.OrderByDescending(q => q.PublicString);
var _mediaFileShare = query.Take(1).SingleOrDefault();
The results using an order by will be dependent on your database and its collation setting.

Or Constraint for QueryOver

I want to get all PartitionStates by name where it exactly meets the partitionName or starts with it when containing a ..
This is the query I have
return session.QueryOver<PartitionState>()
.Where(p => p.Name == partitionName)
.WhereRestrictionOn(p => p.Name).IsLike(partitionName + ".", MatchMode.Start)
.OrderBy(p => p.StartDate).Desc
.Take(1)
.SingleOrDefault<PartitionState>();
The above query produces an AND expression, but i want it to be an OR.
In SQL it should look like this:
SELECT TOP 1 *
FROM PartitionState
WHERE (Name = #partitionName OR Name like #partitionName+'.%')
ORDER BY StartDate DESC
It seems there is no built in method, but it is possible to pass a restriction into where method.
return session.QueryOver<PartitionState>()
.Where(Restrictions.Or(
Restrictions.Where<PartitionState>(p => p.Name == partitionName),
Restrictions.On<PartitionState>(p => p.Name).IsLike(partitionName + ".", MatchMode.Start)))
.OrderBy(p => p.StartDate)
.Desc.Take(1)
.SingleOrDefault<PartitionState>();

LINQ to EF Using a Collection in a Where Clause

I have a main VendorProfile table and a 1-many VendorHistory table that contains status codes and date stamps. The query below works at retrieving only the latest status (status code and date) for each vendor. However, the view allows the user to select checkboxes of any of the status codes to filter the view. So I need to add a where clause that matches ANY of the checkbox StatusSelections.
Model Diagram
public IEnumerable<BrowseStatusModel> BrowseByStatus(int[] StatusSelections)
{
IQueryable<BrowseStatusModel> query = _db.VendorProfiles
.Include("VendorStatusHistory")
.Include("StatusCodes")
.Select(s => new BrowseStatusModel
{
ProfileID = s.ProfileID,
Name = s.Name,
CompanyName = s.CompanyName,
CompanyDBA = s.CompanyDBA,
DateCreated = s.DateCreated,
Status = s.VendorStatusHistories.OrderByDescending(o => o.DateCreated).FirstOrDefault().Id,
StatusDate = s.VendorStatusHistories.OrderByDescending(o => o.DateCreated).FirstOrDefault().DateCreated
})
.OrderBy(x => x.ProfileID);
foreach (int status in StatusSelections)
{
query = query.Where(x => x.Status == status);
}
return query;
}
The above foreach loop works but, unfortunately creates AND condition where ALL selections must be true instead of ANY. I figured I would have to use a where clause with the following in some way but have been unsuccessful at the correct syntax.
.AsQueryable().Any();
Use contains in the place of that foreach loop
query = query.Where(x => StatusSelections.Contains(x.Status))

Grouping NHibernate query results by nullable integer

I'm using NHibernate to query a table that has tuples in the format: (String, Int?), where the integers can be null. So, I want to group my results by number and then sort alphabetically. I can easily do this after I get the query results, but I would like to get NHibernate to formulate a query that does it. Here's an example of the results I would like:
alpha, 1
delta, 4
golf, 3
hotel, 2
lima, 5
charlie, 0
theta, 0
beta, null
echo, null
The three groupings I'm looking for are: (int > 0), (int == 0), and (int = null). Here's the query I'm using:
var devices = session.QueryOver<Table>()
.OrderBy(item => item.Number).Desc
.OrderBy(item => item.Name).Asc
.List();
Currently, I'm sorting them after the query is done, as such:
List<Table> sortedDevices = devices.OrderBy(item => item.Name).Where(item => item.Number > 0).ToList();
sortedDevices = sortedDevices.Concat(devices.OrderBy(item => item.Name).Where(item => item.Number == 0).ToList()).ToList();
sortedDevices = sortedDevices.Concat(devices.OrderBy(item => item.Name).Where(item => item.Number == null).ToList()).ToList();
Is it possible to get NHibernate to group queries like this?
something along the lines:
session.QueryOver<User>()
.Select(Projections.Alias(Projections
.Conditional(Expression.Gt("Number", 0),
Projections.Constant(1),
Projections.Conditional(Expression.Eq("Number", 0),
Projections.Constant(0),
Projections.Constant(-1))),
"group"))
.OrderBy(Projections.Property("group")).Desc
.ThenBy(table => table.Name).Asc
.List();