Question

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.

Was it helpful?

Solution

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top