Индекс RavenDB, охватывающий как один, так и список объектов в документе - PullRequest
3 голосов
/ 19 марта 2012

Сценарий:

В настоящее время я создаю функцию поиска на нашем сайте.Эта функция возвращает альбом, который соответствует всем заданным критериям.То есть.Название альбома, Композитор и т. Д. Я немного знаю о полнотекстовом поиске в Raven, и мне, возможно, придется в конечном итоге попытаться его использовать.

Я надеялся, что смогу использовать вместо этого один индекс и просто запросить индекс.(К сожалению, в настоящее время я недостаточно осведомлен, чтобы сказать, почему я должен / не должен делать это по сравнению с полнотекстовым индексом, поэтому я открыт для предложений:))

Что-то, на что стоит обратить внимание ... Альбомединственная коллекция, которую мы имеем в настоящее время в Raven, так как она предоставляется raven через импорт данных из альтернативной системы.Его можно рассматривать как денормализованное представление всего, что связано с альбомом.

Ниже приведен пример нашего альбома:

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; }            
}

Ниже приведен указатель, который я пытался создать.Поиск по названию работает, но результаты не возвращаются при поиске элемента в коллекции.Я могу только предположить, что это связано с тем фактом, что я не делаю никакой карты / уменьшения и проекции на них.Но это только предположение с моей стороны.

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}

                                                      }
            });

И, наконец, ниже приведен пример моего запроса:

 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;

Заранее благодарен за любую помощь / руководство, которое вы можете предложить,Любая помощь или совет будет очень признателен.

1 Ответ

1 голос
/ 22 марта 2012

Хорошо, я выяснил проблему, с которой столкнулся, и подумал, что поделюсь одним контекстом и позволю другим увидеть ошибки, которые я совершил. Прежде всего, я хотел бы сказать спасибо Даниилу за его ответ. Его решение работает и будет работать просто отлично. Также стоит упомянуть, что мое оригинальное решение тоже будет работать, если вы не допустите глупых ошибок, которые я сделал :).

Ошибка # 1 : Мое решение изначально оказалось неудачным из-за нового ETL документов, о которых я не знал, и старого неправильного индекса. К сожалению я должен был «в сорняках» заметить.

Ошибка # 2 : пример Дэниелса был не совсем тем, что мне было нужно, поэтому мне пришлось немного подправить, и во время настройки я забыл поместить «As <'dynamic'>» в свой запрос, как Пример Даниила имеет.

Если вы хотите использовать результаты вашего запроса как исходный тип clr, в котором документ сохраняется как и , ваш индекс не возвращает тот же тип, тогда важно либо добавить " Как <'dynamic'> () "или" AsProjection <'SomeType'> () "для вашего запроса. Потому что при запросе Raven приведёт тип clr документа к типу clr, который вы укажете в своем индексе. Что в моем случае именно так и произошло. Я хотел работать с результатами как тип Album, но мои документы, возвращаемые из запроса, менялись с типа «Album» на «ReduceResult», как и следовало ожидать. Чего я не ожидал, так это того, что он пометит изменение в документе, который он изменил, и, если был вызван SaveChanges (), теперь он сохранит мой документ как новый тип. Что приводит меня к ошибке номер 3.

Ошибка № 3 : Все, что я делал, было в шаблоне «Единица работы», и я забыл, что в конце моего http-запроса я вызывал ravenSession.SaveChanges (). Это то, что опечатало мою судьбу :(. Поскольку мои типы были изменены во время запроса, упомянутого в ошибке 2, теперь я обнаружил, что в одной коллекции есть документы, которые были разных типов clr.

Конечным результатом было то, что каждый раз, когда я выполнял поиск по моему индексу, который возвращал несколько документов, имеющих разные типы clr, я получал недопустимое исключение приведения. Что еще хуже, я перехватил все свои исключения, чтобы правильно обработать их и вернуть конкретные результаты обратно вызывающему клиенту. Из-за этого мой SaveChanges () всегда срабатывал, и таким образом добавлял документы обратно в мою коллекцию альбомов с другим типом clr. И круг разочарования продолжался.

Так что, используя мой пример, я бы порекомендовал ...

  1. Если вы хотите использовать / воздействовать на альбом в своем коде, убедитесь, что ваш индекс либо возвращает документ в виде альбома, либо ваш индекс возвращает то, что когда-либо уменьшает желаемый результат, но убедитесь, что добавьте метод As <'dynamic'> () или AsProjection <'Sometype'> () в свой запрос. Это должно препятствовать тому, чтобы результат изменил тип документа clr.

  2. Убедитесь, что у вас нет сеанса. Вызывается метод SaveChanges (), о котором вы забыли.

  3. Всегда проверяйте свои индексы, чтобы убедиться в их актуальности.

Короче, не делай таких же глупых ошибок, как я. Видимо мое невежество не имеет границ:)

Еще раз спасибо обоим Даниилам, которые ответили. Я ценю помощь.

...