RE: Updating Metadata (was: Index Raven/DocumentsByEntityName existing in EmbeddableDocumentStore?)

267 views
Skip to first unread message

Alexander Zeitler

unread,
Aug 9, 2012, 6:14:54 PM8/9/12
to rav...@googlegroups.com

Hi,

 

I found this gist and and copying the CreateDocumentsByEntityNameIndex method fixed my Index problem.

 

However, I can’t get the update working properly.

I want to rename an entity in the database and that’s how the implementation looks like:

 

_documentStore.DatabaseCommands.UpdateByIndex(

                "Raven/DocumentsByEntityName",

                new IndexQuery {

                               Query = "Tag:Groups"

                },

                new[]

                               {

 

                                               new PatchRequest

                                                               {

                                                                              Type = PatchCommandType.Modify,

                                                                              Name = "@metadata",

                                                                              Nested = new[]

                                                                                              {

                                                                                                              new PatchRequest

                                                                                                                             {

                                                                                                                                             Type = PatchCommandType.Set,

                                                                                                                                             Name = "Raven-Entity-Name",

                                                                                                                                             Value = new RavenJValue("Categories")

                                                                                                                             }

                                                                                                                             ,

                                                                                                              new PatchRequest

                                                                                                                             {

                                                                                                                                             Type = PatchCommandType.Set,

                                                                                                                                             Name = "Raven-Clr-Type",

                                                                                                                                             Value = new RavenJValue("Foo.Entities.Category, Foo")

                                                                                                                             }

                                                                                              }

                                                               }

 

                               });

 

Again: what am I doing wrong?

 

Alex

 

From: rav...@googlegroups.com [mailto:rav...@googlegroups.com] On Behalf Of Alexander Zeitler
Sent: Donnerstag, 9. August 2012 23:50
To: rav...@googlegroups.com
Subject: [RavenDB] Index Raven/DocumentsByEntityName existing in EmbeddableDocumentStore?

 

Hi,

 

I’m trying to write a test for data migrations using the EmbeddableDocumentStore in the test.

 

When executing this line:

_documentStore.DatabaseCommands.UpdateByIndex("Raven/DocumentsByEntityName",…)

 

I get the following Exception:

Raven.Database.Exceptions.IndexDoesNotExistsException

There is no index named: Raven/DocumentsByEntityName

 

Am I doing something wrong or does the referenced Index not exist by default when using EmbeddableDocumentStore?

 

Alex

Itamar Syn-Hershko

unread,
Aug 9, 2012, 6:47:24 PM8/9/12
to rav...@googlegroups.com
What do you mean by properly? can you show a failing test?

Alexander Zeitler

unread,
Aug 9, 2012, 6:52:44 PM8/9/12
to rav...@googlegroups.com

Now I ran the patch code from below an existing database and noticed, that the patch is execute but the Id’s of the documents still contain the old entity name like “Groups/5” instead of “Categories/5”

How can I update the Id?

Itamar Syn-Hershko

unread,
Aug 9, 2012, 7:03:53 PM8/9/12
to rav...@googlegroups.com
You can't do that with a patch, you will have to issue store and delete commands

Alexander Zeitler

unread,
Aug 9, 2012, 7:09:21 PM8/9/12
to rav...@googlegroups.com

Do you mean DatabaseCommands or Session Commands? Can you give an example please?

 

Thanks

 

Alex

Itamar Syn-Hershko

unread,
Aug 9, 2012, 7:11:08 PM8/9/12
to rav...@googlegroups.com
Doesn't really matter, the easiest way to go is:

var obj = session.Load<Foo>(oldId);
session.Delete(obj);
session.Store(obj, newId);

Alexander Zeitler

unread,
Aug 9, 2012, 7:56:15 PM8/9/12
to rav...@googlegroups.com

That doesn’t work as I’m using Guids and Load<Category>(id) because of the wrong id.

 

Instead I tried:

 

using (var session = _documentStore.OpenSession()) {

                var categoryDefinitions = session.Query<CategoryDefinition>().ToList();

                foreach (var category in categoryDefinitions) {

                               var id = category.Id;

                               session.Delete(category);

                               session.SaveChanges();

                               session.Store(category, Guid.NewGuid());

                               session.SaveChanges();

                               session.Delete(category);

                               session.SaveChanges();

                               session.Store(category, id);

                               session.SaveChanges();

                }

}

 

This works but it feels pretty awkward… (and it only works when CategoryDefinitions collection has been empty).

 

Another approach has been this:

 

var groups = _session.Query<Group>();

foreach (var category in groups.Select(group => new Category () {

                Id = group.Id,

                // copy  all properties

})) {

                _session.Store(category);

}

}

 

But that requires to have both, Group and Category class, in the solution instead of just renaming Group to Category.

 

Will try your approach tomorrow with string id’s.

Itamar Syn-Hershko

unread,
Aug 9, 2012, 8:01:28 PM8/9/12
to rav...@googlegroups.com
You can use DatabaseCommands and work with RavenJObject directly, that will be faster and more straight forward

Alexander Zeitler

unread,
Aug 10, 2012, 5:27:11 AM8/10/12
to rav...@googlegroups.com
Now I started from scratch and now even renaming does not work.
I created a gist:  https://gist.github.com/3312858 

Alex

From: rav...@googlegroups.com [rav...@googlegroups.com] on behalf of Alexander Zeitler [alexande...@pdmlab.com]
Sent: Friday, August 10, 2012 1:56 AM
To: rav...@googlegroups.com
Subject: RE: [RavenDB] RE: Updating Metadata (was: Index Raven/DocumentsByEntityName existing in EmbeddableDocumentStore?)

Alexander Zeitler

unread,
Aug 10, 2012, 6:17:20 AM8/10/12
to rav...@googlegroups.com
Found it: must use plurals instead of singulars for Tag + Raven-Entity-Name.

Alex

Sent: Friday, August 10, 2012 11:27 AM

Alexander Zeitler

unread,
Aug 10, 2012, 6:39:02 AM8/10/12
to rav...@googlegroups.com
I tried this but I didn't find a way to modify the Id of a document using DatabaseCommands.
I don't want to create a completely new id, I want to rename the part identifying the collection of where the entity/document is assigned to.

Groups/1 should become Categories/1

Alex


From: rav...@googlegroups.com [rav...@googlegroups.com] on behalf of Itamar Syn-Hershko [ita...@hibernatingrhinos.com]
Sent: Friday, August 10, 2012 2:01 AM

Oren Eini (Ayende Rahien)

unread,
Aug 10, 2012, 7:03:02 AM8/10/12
to rav...@googlegroups.com
You cannot do that. 
You have to delete and create.

Alexander Zeitler

unread,
Aug 10, 2012, 7:03:29 AM8/10/12
to rav...@googlegroups.com
Another one:

using(var session = _documentStore.OpenSession()) {
var categories = session.Query<Category>().As<RavenJObject>();
foreach(var category in categories) {
var metadata = session.Advanced.GetMetadataFor(category);
metadata["@id"] = metadata.Value<string>("@id").Replace("groups", "categories");
session.Store(category);
session.SaveChanges();
}
}

Id gets not updated.

Alex

From: rav...@googlegroups.com [rav...@googlegroups.com] on behalf of Alexander Zeitler [alexande...@pdmlab.com]
Sent: Friday, August 10, 2012 12:39 PM
To: rav...@googlegroups.com
Subject: RE: [RavenDB] RE: Updating Metadata (was: Index Raven/DocumentsByEntityName existing in EmbeddableDocumentStore?)

Oren Eini (Ayende Rahien)

unread,
Aug 10, 2012, 7:04:05 AM8/10/12
to rav...@googlegroups.com
You cannot update ids.

Alexander Zeitler

unread,
Aug 10, 2012, 7:08:31 AM8/10/12
to rav...@googlegroups.com
Just for clarity: 

Delete / Create a new entity or Delete / Create a new Id in metadata?

Alex

From: rav...@googlegroups.com [rav...@googlegroups.com] on behalf of Oren Eini (Ayende Rahien) [aye...@ayende.com]
Sent: Friday, August 10, 2012 1:03 PM

Oren Eini (Ayende Rahien)

unread,
Aug 10, 2012, 7:10:12 AM8/10/12
to rav...@googlegroups.com
Delete entity
SaveChanges
Create entity
SaveChanges

Alexander Zeitler

unread,
Aug 10, 2012, 7:43:11 AM8/10/12
to rav...@googlegroups.com
Thanks

Alex

From: rav...@googlegroups.com [rav...@googlegroups.com] on behalf of Oren Eini (Ayende Rahien) [aye...@ayende.com]
Sent: Friday, August 10, 2012 1:10 PM

Chris Marisic

unread,
Aug 10, 2012, 8:53:31 AM8/10/12
to rav...@googlegroups.com
This is how I've mutated object ids in the past when I needed to:


                var docs = Session.Advanced.DatabaseCommands.StartsWith(myDocPrefix, skip, take);

            var commandDatas = new List<ICommandData>();
            var transactionInformation = new TransactionInformation {Id = Guid.NewGuid(), Timeout = TimeSpan.FromSeconds(61)};           

            foreach (JsonDocument doc in docs )
            {

                //Delete old document
                commandDatas.Add(new DeleteCommandData()
                                     {
                                         Etag = doc.Etag,
                                         Key = doc.Key,
                                         TransactionInformation = transactionInformation
                                     });

                //mutate existing key that's stored in the document's json
                doc.DataAsJson["Id"] = doc.DataAsJson["Id"].ToString().Replace(oldId, newId);

                //prepare to save mutated
                commandDatas.Add(new PutCommandData
                                     {
                                         Document = doc.DataAsJson,
                                         Key = doc.Key.Replace(oldId, newId),
                                         Metadata = doc.Metadata,
                                         TransactionInformation = transactionInformation
                                     });
            }

           
            Session.Advanced.DatabaseCommands.Batch(commandDatas);        
        }

Note this code was originally used for only updating a few docs at a time, you have additional considerations if you have more than 1024 docs (have to do this in batches) and you may wish to increase the timeout for doing bulk mutations on the transaction. Also I was only doing partial replacements hence the string.Replace usages that may or maynot be relevant for your use case.
Reply all
Reply to author
Forward
0 new messages