Null values from string[].FirstOrDefault() can't be queried

17 views
Skip to first unread message

Andrej Krivulčík

unread,
Nov 30, 2016, 5:35:08 AM11/30/16
to RavenDB - 2nd generation document database
When using map-reduce index and there is a field retrieved using FirstOrDefault(), which returns (string)null, the records can't be queried using [[NULL_VALUE]].

When looking at Terms in Studio, the NULL_VALUE is not present.

Failing test:

    public class StringIndexingTest : RavenTestBase
   
{
       
public class Employee
       
{
           
public string Id { get; set; }
           
public string FirstName { get; set; }
           
public string StrVal { get; set; }
       
}

       
public class EmployeeView
       
{
           
public string Id { get; set; }
           
public string FirstName { get; set; }
           
public string StrVal { get; set; }
       
}

       
public class EmployeeIndex : AbstractMultiMapIndexCreationTask<EmployeeView>
       
{
           
public EmployeeIndex()
           
{
               
AddMap<Employee>(
                    employees
=> from employee in employees
                                 
select new
                                 
{
                                     employee
.Id,
                                     employee
.FirstName,
                                     employee
.StrVal,
                                 
});

               
Reduce = results => from result in results
                                   
group result by result.Id
                                   
into g
                                    let employee
= g.First()
                                   
select new
                                   
{
                                       
Id = employee.Id,
                                       
FirstName = employee.FirstName,
                                       
StrVal = g.Select(x => x.StrVal).FirstOrDefault(x => !string.IsNullOrEmpty(x)), // results of this construct can't be queried using [[NULL_VALUE]]
                                   
};
           
}
       
}

       
[Fact]
       
public void StringArraysWithNoDataCanBeQueried()
       
{
           
using (var store = NewRemoteDocumentStore())
           
{
               
new EmployeeIndex().Execute(store);

               
using (var session = store.OpenSession())
               
{
                    session
.Store(new Employee{ Id = "1", FirstName = "A", StrVal = null });
                    session
.Store(new Employee{ Id = "2", FirstName = "B", StrVal = "B" });
                    session
.SaveChanges();
               
}

               
using (var session = store.OpenSession())
               
{
                    session
.Query<EmployeeView, EmployeeIndex>()
                       
.Customize(x => x.WaitForNonStaleResults())
                       
.Count();
               
}

               
using (var session = store.OpenSession())
               
{
                   
var nonNullCount = session.Query<EmployeeView, EmployeeIndex>()
                       
.Where(x => x.StrVal != null)
                       
.Count();
                   
Assert.Equal(1, nonNullCount); // works correctly

                   
var nullCount = session.Query<EmployeeView, EmployeeIndex>()
                       
.Where(x => x.StrVal == null)
                       
.Count();
                   
Assert.Equal(1, nullCount); // doesn't find the document
               
}
           
}
       
}
   
}



Oren Eini (Ayende Rahien)

unread,
Nov 30, 2016, 5:37:11 AM11/30/16
to ravendb
Use:

 g.Select(=> x.StrVal).FirstOrDefault(=> !string.IsNullOrEmpty(x)) ?? null;

The reason is that this is effectively an missing value, so we don't index it.


Hibernating Rhinos Ltd  

Oren Eini l CEO Mobile: + 972-52-548-6969

Office: +972-4-622-7811 l Fax: +972-153-4-622-7811

 


--
You received this message because you are subscribed to the Google Groups "RavenDB - 2nd generation document database" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ravendb+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Andrej Krivulčík

unread,
Nov 30, 2016, 5:39:57 AM11/30/16
to RavenDB - 2nd generation document database
Is the entire record not present in the index in this case?

Oren Eini (Ayende Rahien)

unread,
Nov 30, 2016, 6:11:21 AM11/30/16
to ravendb
Yes, but the specific field isn't

Andrej Krivulčík

unread,
Nov 30, 2016, 6:38:21 AM11/30/16
to RavenDB - 2nd generation document database
Is there a reason for this handling? What's the difference between null value and missing value in this case? Is there a use case for this where it's desirable to not use null as the result of FirstOrDefault() automatically (without explicitly stating it with ?? null)?
To unsubscribe from this group and stop receiving emails from it, send an email to ravendb+u...@googlegroups.com.

Oren Eini (Ayende Rahien)

unread,
Nov 30, 2016, 7:05:13 AM11/30/16
to ravendb
The problem is that we are doing null handling, so you can do things like:

                                        StrVal = g.Select(=> x.StrVal).FirstOrDefault(=> !string.IsNullOrEmpty(x)).ToUpper()

And it will work without throwing an NRE.

When we get to indexing, we assume that this is a missing value and not important, so we don't index it.
To unsubscribe from this group and stop receiving emails from it, send an email to ravendb+unsubscribe@googlegroups.com.

Andrej Krivulčík

unread,
Nov 30, 2016, 7:14:07 AM11/30/16
to RavenDB - 2nd generation document database
Makes sense, thanks.
Reply all
Reply to author
Forward
0 new messages