1

In a question I asked in the RavenDB discussion boards about making a large number of similar indexes, I was told that I should not make "so many indexes that do the same thing" and told I should make a "string index" instead - the exact words were ...

There is no reason to have so many indexes that do the same thing. Create an index with:

from d in docs select new { d.Id, d.Name, Collection = d["@metadata"]["Raven-Entity-Name"] }

And query on that.

Reference Topic

I do not understand at all what this means, I have read the raven documentation many times before today, and I'm still very lost and in the dark.

The best I can come up with; Or the closest I understand, is something kind of like this...

RavenSession.Advanced.DocumentStore.DatabaseCommands.PutIndex("Index/Name",
    new Raven.Client.Indexes.IndexDefinitionBuilder<IMayTransform>{
        Map = results => from result in results
            select new{
                result.Id,
                result.Name,
                result["@metadata"]["Raven-Entity-Name"]
            }
    });

Update

Adding the interfaces involved, by request.

    public interface IMayTransform : IHasIdentity, IHasName { }

    public interface IHasIdentity {
        /// <summary>
        /// A string based identity that is used by raven to store the entity.
        /// </summary>
        string Id { get; set; }
    }

    public interface IHasName {
        /// <summary>
        /// The friendly display name for the entity.
        /// </summary>
        string Name { get; set; }
    }

But this does not work. First of all, the part about ["@metadata"] is not compiling; I do not even understand the purpose if its existence in the example I was cited. I do not understand how I am supposed to query something like this, either - or where it goes, or where it is defined, how it is called, etc. I have literally no concept of what a "string index" is.

On top of that, I do not comprehend how I add analyzers to this. Any help is appreciated; This has been a horrible, horrible morning and I am frantic to get at least some modicum of work done, but this is leaving me very confused.

IMayTransform is an interface that every entity that needs to fit this implements.

Update (Again)

Between the answer here on stack overflow, and the glorious help from Ayende on the ravendb google groups, I have the following index that works. And I HATE IT.

public class EntityByName : AbstractIndexCreationTask {
    public override IndexDefinition CreateIndexDefinition() {
        return new IndexDefinition {
            Map = "from doc in docs let collection = doc[\"@metadata\"][\"Raven-Entity-Name\"] select new { doc.Id, doc.Name, doc.Abbreviation,  Group_Name = doc.Group.Name, Tags = doc.Tags.Select( r => r.Name ), collection };",
            Indexes = {
                {"Name", FieldIndexing.Analyzed },
                {"Abbreviation", FieldIndexing.Analyzed },
                {"Tags", FieldIndexing.Analyzed },
                {"Group.Name", FieldIndexing.Analyzed }
            },
            Fields ={
                { "Name" },
                { "Abbreviation" },
                { "Group.Name" },
                //{ "Tags" }
            },
            Stores ={
                { "Name", FieldStorage.Yes },
                { "Abbreviation", FieldStorage.Yes },
                { "Group.Name", FieldStorage.Yes },
                //{ "Tags", FieldStorage.Yes }
            },
            SortOptions = {
                { "collection", SortOptions.String },
                { "Name", SortOptions.String }
            }
        };
    }
}

This does exactly what I need it to do. It is fast, efficient, it works fine, it gives me no trouble, but hard coding everything into a string query is driving me nuts. I am closing this question and opening a new one concerning this, but if anyone has suggestions on ways I can get away from this, I would love to hear them. This is an issue of personal desire, not functional need.

Ciel
  • 4,290
  • 8
  • 51
  • 110

1 Answers1

0

try it like this

RavenSession.Advanced.DocumentStore.DatabaseCommands.PutIndex(
    "Index/Name", 
    new IndexDefinition {
        Map = "from d in docs select new { Id = d.Id, Name = [\"@metadata\"][\"Raven-Entity-Name\"]}"
    });

now you see, what a "string index" is as well.

BTW: there is a build-in index, that does a similar thing as this: Raven/DocumentsByEntityName

Usage:

public class Entity 
{
    public string Id { get; set; }

    public string Name { get; set; } }
}

session.Query<Entity>("Index/Name").Where(x => x.Name == "Foo");

Further Explanation:

There is now way to build indexes using interfaces only. To achieve what you want, Raven would need to implement a BaseEntity that populates the matadata as properties and all documents must derive from that Entity. But that is not going to happen and nobody wnats that. But, when designing your documents, you could integrate the entity name yourself, like

public class EntityBase
{
    public EntityBase()
    {
        this.TypeName = this.GetType().Name;
    }

    public string Name { get; set; }

    public string TypeName { get; set; }
}

public class Person : EntityBase
{
    public string FirstName { get; set; }

    public string LastName { get; set; }
}

Now you could build an ravendb index based on EntityBase and query TypeName

esskar
  • 10,638
  • 3
  • 36
  • 57
  • I also not understand how to query this exactly. – Ciel Apr 02 '14 at 13:24
  • it has to be done in a string, because raven does not know your objects at this point – esskar Apr 02 '14 at 13:31
  • i also added the usage. Keep in mind, for deserialisation you have to gave a actual class, interface is no real use here. – esskar Apr 02 '14 at 13:36
  • Could an interface not be used for the index definition, but an actual class used when calling the index? – Ciel Apr 02 '14 at 14:41
  • I'm not understanding what "Raven-Entity-Name" is for. This basically means I have to always query based on the actual name of the object, not the entity? I'm confused. – Ciel Apr 02 '14 at 14:47
  • I am sorry, I have tried the example you gave me verbatim, and it does not work. \ – Ciel Apr 02 '14 at 15:05
  • what does not work mean? Any errors? try doing `session.Query("Index/Name").ToArray()` and check the result! – esskar Apr 02 '14 at 22:04
  • Ok. Through a lot of work I have made a string index that works. I have to say that I absolutely hate them. Is there any way to achieve dynamic indexes without just hardcoding the whole linq expression as a string? Lol. It is driving me nuts – Ciel Apr 03 '14 at 18:26
  • Hey, I am accepting your answer as it did lead me to a more complete solution. I hate the solution. It works and does what I asked for, but my OCD cannot abide it. If you have suggestions to help me there, I'd love to hear them. Thank you for all of your patience. – Ciel Apr 03 '14 at 18:30