RavenDB index covering one as well as list of objects in document

Scenario:

I am currently creating a search function on our site. This function is to return an album that meets all the specified criteria. I.e. Album title, composer, etc. I know a little about the full text search that is inside Raven, and I may have to end up trying to use it.

I was hoping that maybe I could only use one index and just query the index. (Unfortunately, I am not knowledgeable enough at this time to say why I should / should not do this versus a full text index, so I am open to suggestions :))

Something worth noting ... The Album is the only collection we currently have in Raven, as it is provided to the Raven by importing data from an alternate system. It can be thought of as a denormalized representation of everything related to the album.

Below is an example of our album:

public class Album
{
    public string Id { get; set; }
    public string Title { get; set; }
    public string Description { get; set; }
    public List<string> Composers { get; set; }
    public List<string> MusicCategories { get; set; }
    public List<string> PerformingGroups { get; set; }
    public List<string> Instruments { get; set; }            
}

      

Below is the index that I tried to create. Searching by name works, but no results are returned when you search for an item in the collection. I can only imagine that this is due to the fact that I do not make any maps / cuts and projections on them. But this is only a guess on my part.

ravenSessionManager.DocumentStore.DatabaseCommands
            .PutIndex("AlbumsBySearchCriteria", new IndexDefinitionBuilder<Album>
            {
                Map = albums => from a in albums
                                select
                                    new
                                    {
                                        a.Title,
                                        a.Composers,
                                        a.MusicCategories,
                                        a.Instruments
                                    },
                Indexes =
                                                      {
                                                          {x => x.Title, FieldIndexing.Analyzed},
                                                          {x => x.Composers, FieldIndexing.Analyzed},FieldIndexing.Analyzed},
                                                          {x => x.MusicCategories, FieldIndexing.Analyzed},FieldIndexing.Analyzed},
                                                          {x => x.Instruments, FieldIndexing.Analyzed}

                                                      }
            });

      

And finally, below is an example of my request:

 var query = (from a in _documentSession.Query<Album>("AlbumsBySearchCriteria")
                         select a);

            if(!string.IsNullOrEmpty(criteria.Title))
                query = query.Where(a => a.Title.StartsWith(criteria.Title));
            if (!string.IsNullOrEmpty(criteria.Composer))
                query = query.Where(a => a.Composers.Any(c => c.StartsWith(criteria.Composer)));
return query;

      

Thanks in advance for any help / guidance you can offer. Any help or advice would be really appreciated.

+3


source to share


1 answer


Ok so I figured out the problem I was facing and I thought I would share some context and let others see the mistakes I made. First of all, I would like to thank Daniel for his answer. His solution works and will work fine. It's also worth mentioning that my original solution will work too, unless you make the stupid mistakes I did :).

Mistake number 1 . Initially my solution failed due to new ETL documents that I was not aware of and old wrong index. Unfortunately, I had to "in the weeds" notice.

Mistake # 2 : Daniels's example was not exactly what I wanted, so I needed to tweak it a bit, and when setting up I forgot to put "As <" dynamic "> in my query as Daniel's example.

If you want to use the results of your query as the original clr type that is stored in the document like and , your index does not return the same type, then it is important to either add "Like <'dynamic'> ()" or "AsProjection <'SomeType' > () "in your request. Because when prompted, Raven will infer the clr-type of the document to the clr-type that you specify in your index. Which is exactly what happened in my case. I wanted to use my results as an album of type, but my documents returned from the query were changing from type "Album" to "Reduce Time" as one would expect. I didn't expect this to mean a change in the document it changed and if SaveChanges () is called it will now save my document as a new type.This leads me to error # 3.

Mistake number 3 . Everything I did was in the Unit of Work template and I forgot that at the end of my HTTP request I called ravenSession.SaveChanges (). This is what sealed my destiny :( Since my types were changed during the request mentioned in error 2, now I found that I have documents in the same collection that were different clr types.



The end result was that every time I searched my index that returned multiple documents that have different clr types, I would get an invalid cast exception. To make things worse, I took advantage of all exceptions so that I can handle them appropriately and return specific results back to the caller. Because of this, my SaveChanges () is always triggered and thus adds documents back to my album collection with a different clr type. And the circle of disappointment continued.

So, using my example, my recommendation would be ...

  • If you want to use / act on an album in your code, make sure that your index either returns the document as an album, or your index returns what ever decreases the result you want, but that you add the As method to your query <'dynamic'> () or AsProjection <'Sometype'> (). This should prevent the clr-type document result from changing.

  • Make sure you don't have a session. The call to SaveChanges () is being called that you forgot about.

  • Always check your indexes to make sure they are up to date.

In short, don't make the same silly mistakes I did. Apparently my ignorance has no boundaries :)

Thanks again to both Daniels who responded. I appreciate the help.

+1


source







All Articles