Problem with AbstractIndexCreationTask when using FindIdentityProperty conventions

84 views
Skip to first unread message

Jonas Hedlind

unread,
Aug 21, 2014, 7:44:00 AM8/21/14
to rav...@googlegroups.com

I use lower case "id" as my document id convention in RavenDB (build 2910 and 2916)
var store = new DocumentStore
            {                                 
                Conventions =
                {
                    FindIdentityProperty = q => q.Name == "id"
                }
            };

Say I have an index on Tasks created using: ( BTW.. just for show, not actually using this index )

public class Task
{
    public string id { get; set; }
    public string Name { get; set; }
}

public class Task_Index : AbstractIndexCreationTask<Task, Task_Index.TaskIndexData>
    {
        public class TaskIndexData
        {  
            public string TaskId 
{ get; set; }
            public string Name { get; set; }
        }

        public Task_Index()
        {
            Map = Tasks => from t in Tasks
                           select new TaskIndexData
                           {                               
                               TaskId = t.id,
                                                              Name = t.Name,                               
                           };
        }
    }

Looking in Raven studio the generated index looks something like this
docs.Tasks.Select(t => new {
    TaskID = t.id, //does not populate unless I use t.Id
    Name = t.Name
})

The TaskId property in the index is always null unless I manually change the index to use t.Id..
What am I missing here? The __document_id property is there but how do I use it from the Map/Reduce in AbstractIndexCreationTask?
Seems like AbstractIndexCreationTask should look at the documnt id convention and change the lower case "id" to "Id" in the generated index?..

Chris Marisic

unread,
Aug 21, 2014, 10:58:47 AM8/21/14
to rav...@googlegroups.com
I'm pretty sure those conventions are merely client conventions. That the server has no knowledge of them and as you see it behaves in its standard fashion regarding the special treatment of "Id" and __document_id

Just stop fighting core conventions. You are just setting yourself up for pain. Just use Id and you won't regret it. Just like every person that uses int Id at some point in their system they come to regret their choice. Just because you can, doesn't mean you should.

Oren Eini (Ayende Rahien)

unread,
Aug 21, 2014, 12:25:42 PM8/21/14
to ravendb
How are you executing the index?

Because this code:

var convention = new DocumentConvention
{
FindIdentityProperty = info => info.Name == "id"
};

var indexDefinition = new Task_Index
{
Conventions = convention
}.CreateIndexDefinition();


Generate this index:

docs.Tasks.Select(t => new {
    TaskId = t.__document_id,
    Name = t.Name
})

And this test passes:

Fact]
ublic void GenerateCorrectIndex()

using (var store = NewDocumentStore())
{
store.Conventions.FindIdentityProperty = info => info.Name == "id";
new Task_Index().Execute(store);

var indexDefinition = store.DatabaseCommands.GetIndex("Task/Index");
Assert.Contains("__document_id", indexDefinition.Map);

}




Oren Eini

CEO


Mobile: + 972-52-548-6969

Office:  + 972-4-622-7811

Fax:      + 972-153-4622-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+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Jonas Hedlind

unread,
Aug 21, 2014, 1:06:20 PM8/21/14
to rav...@googlegroups.com
Running it locally.. not embedded.. like you, I could not create a failing test using the embedded db in RavenTestBase... 

    [TestClass]
    public class UnitTest3
    {
        [TestMethod]
        public void TestMethod1()
        {
            IDocumentStore store = new DocumentStore
            {
                Url = "http://localhost:8080",                
                Conventions =
                {
                    FindIdentityProperty = q => q.Name == "id"
                }
            };
            store.Initialize();
            string dbName = "SampleData";
            store.DatabaseCommands.EnsureDatabaseExists(dbName);
            
            SampleData_Index ind = new SampleData_Index();
            store.DatabaseCommands.ForDatabase(dbName).DeleteIndex(ind.IndexName);
            store.DatabaseCommands.ForDatabase(dbName).PutIndex(ind.IndexName,ind.CreateIndexDefinition());
            
            using (var session = store.OpenSession(dbName))
            {
                session.Store(new SampleData() { Name = "Raven" });
                session.Store(new SampleData() { Name = "Crow" });
                session.SaveChanges();
                var result = session.Advanced.LuceneQuery<SampleData,SampleData_Index>()
                            .WaitForNonStaleResults()
                            .WhereEquals("Name","Crow")
                            .FirstOrDefault();

                Assert.IsNotNull(result);

                var result2 = session.Advanced.LuceneQuery<SampleData, SampleData_Index>()                            
                            .WhereEquals("TaskId", result.id )
                            .FirstOrDefault();

                Assert.IsNotNull(result2); //Fails!
            }
        }
    }

    public class SampleData
    {
        public string id { get; set; }
        public string Name { get; set; }
    }

    public class SampleData_Index : AbstractIndexCreationTask<SampleData, SampleData_Index.SampleIndexData>
    {
        public class SampleIndexData
        {
            public string TaskId { get; set; }
            public string Name { get; set; }
        }

        public SampleData_Index()
        {
            Map = Tasks => from t in Tasks
                           select new SampleIndexData
                           {
                               TaskId = t.id,
                               Name = t.Name,
                           };
        }
    }

Index looks like this after the unit test
docs.SampleDatas.Select(t => new {
    TaskId = t.id,
    Name = t.Name
})

Oren Eini (Ayende Rahien)

unread,
Aug 21, 2014, 1:42:17 PM8/21/14
to ravendb
What build are you using?

Chris Marisic

unread,
Aug 21, 2014, 4:16:35 PM8/21/14
to rav...@googlegroups.com
Reviewing Ayende's sample and your sample, the difference is Ayende provided the conventions to the index. The code below is not doing that

new SampleData_Index();

vs

new SampleData_Index { Conventions = convention }

Jonas Hedlind

unread,
Aug 21, 2014, 4:23:38 PM8/21/14
to rav...@googlegroups.com
I will double check but the client is probably build 2879..

Oren Eini (Ayende Rahien)

unread,
Aug 22, 2014, 2:02:27 AM8/22/14
to ravendb
The problem is how you execute it:



            SampleData_Index ind = new SampleData_Index();
            store.DatabaseCommands.ForDatabase(dbName).DeleteIndex(ind.IndexName);
            store.DatabaseCommands.ForDatabase(dbName).PutIndex(ind.IndexName,ind.CreateIndexDefinition());

NEVER do this

Basically, you are FORCING the database to delete and create the index, even if it didn't change.

Use:

new SampleData_Index().Execute(store);

And it will just work for you.

Jonas Hedlind

unread,
Aug 22, 2014, 3:04:21 AM8/22/14
to rav...@googlegroups.com
The delete/put index is just the way I do it in the unit test.

so 
new SampleData_Index().Execute(store); 
will add the index to the correct database? 

I will try that
Thanks

Oren Eini (Ayende Rahien)

unread,
Aug 22, 2014, 3:12:20 AM8/22/14
to ravendb
Yes, assuming that you are using the DefaultDatabase.
For a specific database, use this:


// deploy index to `Northwind` database
    // using store `Conventions`
    new Orders_Totals().Execute(store.DatabaseCommands.ForDatabase("Northwind"), store.Conventions);



Oren Eini

CEO


Mobile: + 972-52-548-6969

Office:  + 972-4-622-7811

Fax:      + 972-153-4622-7811





--
Reply all
Reply to author
Forward
0 new messages