Форматирование многогранных результатов поиска RavendDB

В настоящее время я играю с фасетным поиском после прочтения документа RavenDB.

Возвращаемый результат в порядке, но есть небольшая проблема. Поскольку результат получается как

IDictionary<string, IEnumerable<FacetValue>>

необходимо перебрать его и выполнить некоторые причудливые манипуляции со строками, чтобы отформатировать результат и отобразить его в PartialView. Более конкретно этот аспект:

new Facet
    {
        Name = "Value_Range",
        Mode = FacetMode.Ranges,
        Ranges =
            {
                "[NULL TO Dx500.0]",
                "[Dx500.0 TO Dx1000.0]",
                "[Dx1000.0 TO Dx2500.0]",
                "[Dx2500.0 TO Dx5000.0]",
                "[Dx5000.0 TO NULL]",
            }
    } 

View код:

@fv.Range

Вот эта "красивая" строка, которая выводится в представлении: [Dx400.0 TO Dx600.0]

RavenDB использует указанный выше префикс Dx для создания числа для преобразование строк.

Controller код, в котором результат фасета передается конкретному ViewModel:

var facetResults = DocumentSession.Query<Realty>("RealtyFacets")
            //.Where(x => x.Value >= 100 && x.Value <= 1000)
            .ToFacets("facets/RealtyFacets").ToArray();

var model = new RealtyFacetsViewModel();

model.Cities = facetResults[0];
model.Purposes = facetResults[1];
model.Types = facetResults[2];
model.Values = facetResults[3];

return PartialView("RealtyFacets", model);

Есть ли какой-либо другой/лучший способ получения результатов многогранного поиска, чтобы для форматирования возвращаемых данных не нужно было выполнять никаких манипуляций со строками?

По предложению Айенде я сделал это в своем контроллере:

foreach (var val in facetResults[3].Value)
{
    switch(val.Range)
    {
        case "[Dx0.0 TO Dx200.0]":
            val.Range = string.Format("{0:C2} {1} {2:C2}",
                                        0, @Localization.to, 200);
            break;
        case "[Dx200.0 TO Dx400.0]":
            val.Range = string.Format("{0:C2} {1} {2:C2}",
                                        200, @Localization.to, 400);
            break;
        case "[Dx400.0 TO Dx600.0]":
            val.Range = string.Format("{0:C2} {1} {2:C2}",
                                        400, @Localization.to, 600);
            break;
        case "[Dx600.0 TO Dx800.0]":
            val.Range = string.Format("{0:C2} {1} {2:C2}",
                                        600, @Localization.to, 800);
            break;
        case "[Dx800.0 TO Dx1000000.0]":
            val.Range = string.Format("{0:C2} {1} {2:C2}",
                                        800, @Localization.to, 1000000);
            break;
    }
}

model.Values = facetResults[3];

person Leniel Maccaferri    schedule 23.02.2012    source источник
comment
@ Просто чтобы добавить к ответу Орена, я реализовал API-интерфейс фасета таким образом, потому что это было проще ;-) Кроме того, заставляя разработчика писать точный запрос Lucene для каждого фасета, обеспечивается большая гибкость. В противном случае API должен был бы знать все возможные сценарии группировки, которые вы хотели бы использовать. Но в результате API на самом деле не знает, что такое ваша группировка, он просто выполняет запрос lucene, который вы ему даете.   -  person Matt Warren    schedule 24.02.2012
comment
Однако вы можете немного упростить свой код, используя более общий код, который преобразует Dx800.0 -> 800.0. См. здесь, как RavenDB делает это внутри, github.com /ravendb/ravendb/blob/master/Raven.Abstractions/   -  person Matt Warren    schedule 24.02.2012
comment
На самом деле даже лучше просто вызвать NumberUtils.StringToNumber(..) и попросить RavenDB преобразовать его для вас. Код находится в Raven.Abstractions, доступ к которому вы можете получить в клиентском API.   -  person Matt Warren    schedule 24.02.2012
comment
@MattWarren: отличная работа над Facet API, мой друг. Продолжайте развиваться... Я воспользовался вашим советом. Смотрите мой ответ ниже. Что вы думаете?   -  person Leniel Maccaferri    schedule 24.02.2012
comment
Да, это в точку. Также вы можете использовать другие методы в этом классе, чтобы сделать обратное, то есть сгенерировать строку диапазона из заданных чисел. Таким образом, создание документа по настройке фасета немного упрощается.   -  person Matt Warren    schedule 24.02.2012
comment
Да, Мэтт, это даже можно настроить, скажем, в Web.config. Нужно просто извлечь эти числа и использовать их при построении фасетов. Фантастика! :D   -  person Leniel Maccaferri    schedule 24.02.2012


Ответы (2)


Согласно @MattWarren, я использовал:

foreach (var val in facetResults[3].Value)
{
    // Original string format: [Dx5000.0 TO Dx10000.0]
    var limits = val.Range.Split(new string[] { "TO", "[", "]", " " },
                                 StringSplitOptions.RemoveEmptyEntries);

    // Leveraging RavenDB NumberUtil class...
    val.Range = string.Format("{0:C0} {1} {2:C0}",
    Raven.Abstractions.Indexing.NumberUtil.StringToNumber(limits.ElementAt(0)),
    @Localization.to,
    Raven.Abstractions.Indexing.NumberUtil.StringToNumber(limits.ElementAt(1)));      
}
person Leniel Maccaferri    schedule 24.02.2012

Leniel, В своем коде создайте словарь, который будет отображать значение фасета и отображаемую строку. В настоящее время RavenDB не имеет возможности влиять на значение фасета.

person Ayende Rahien    schedule 23.02.2012
comment
В ПОРЯДКЕ. Я понял идею. Поскольку я не видел образца этого в работе на стороне просмотра, я подумал, что будет способ получить его прямо из самой RavenDB... - person Leniel Maccaferri; 24.02.2012