【问题标题】:RavenDB - Index sorting for Alphanumeric propertyRavenDB - 字母数字属性的索引排序
【发布时间】:2015-05-27 18:14:03
【问题描述】:

我正在尝试索引应按如下方式排序的字母数字属性:

WS1-1-14-1
WS1-1-15-1
WS1-1-15-2
WS1-1-15-3

我创建了一个删除属性的非数字字符的索引,并将 SortOptions 设置为 Int,这样我就可以像上面那样排序了。

这是我的索引定义:

        Map = fixtures => from f in fixtures
                select new
                       {
                           FixtureNumber = f.FixtureNumber.Replace("-", "").Replace("WS", ""),
                       };

        Sort(x => x.FixtureNumber, SortOptions.Int);

当我在索引上排序时排序工作正常:

session.Query<Fixture, Fixtures_All>.OrderBy(x => x.FixtureNumber).ToList()

但我的问题是,当我对我的 Fixture 文档进行动态查询时,它就像查询仍在使用我的索引:

session.Query<Fixture>.FirstOrDefault(x => x.FixtureNumber == "WS1-1-1");

不返回任何结果,我希望它会因为我没有查询我的索引。但以下确实有效,我觉得很奇怪:

var fixNo = "WS1-15-1".Replace("-", "").Replace("WS", "");
session.Query<Fixture>.FirstOrDefault(x => x.FixtureNumber == fixNo);

为什么我的索引会影响这个动态索引查询?

还有没有更好的方法来索引我的属性而无需使用字符串替换来使其成为整数?

谢谢

注意:

如果我只是在 SortOptions 上使用默认字符串比较器,结果会像这样排序:

WS1-1-15-1
WS1-1-15-10
WS1-1-15-2
WS1-1-15-3
...

【问题讨论】:

    标签: c# .net indexing ravendb


    【解决方案1】:

    在进行动态索引时,Raven 将始终查找给定类型的索引和该类型的索引属性(按名称)。如果找不到,它会先自动生成一个。

    当您发出以下查询时:

    session.Query<Fixture>.FirstOrDefault(x => x.FixtureNumber == "WS1-1-1");
    

    Raven 会发现在 Fixtures_All 索引定义的属性 FixtureNumber 上确实有一个索引。这里的问题是存储在索引中的 FixtureNumber 被更改(去除了破折号和字母),因此 Raven 将使用它来映射您的查询(它不知道它已被更改)。

    如果您查看 Raven 工作室中的索引,您可以选择“索引条目”来显示磁盘上实际索引的样子:

    这就是发出查询时没有得到任何结果的原因。

    如果您想在索引中使用更改的属性,您可以执行以下操作:

    Map = fixtures => from f in fixtures
        select new
        {
            ShortenFixtureNumber =  f.FixtureNumber.Replace("-", "").Replace("WS", ""),
            FixtureNumber = f.FixtureNumber
        };
    
    Sort("ShortenFixtureNumber", SortOptions.Int);
    

    然后你可以创建一个我喜欢称之为“查询模型”的东西(不确定这是否是正确的名称):

    public class FixtureQueryModel
    {
        public string FixtureNumber { get; set; }
        public int ShortenFixtureNumber { get; set; }
    }
    

    有了这个,我既可以使用“查询模型”通过索引查询,也可以直接查询类型:

    var fixture = session.Query<FixtureQueryModel, Fixtures_All>()
                            .Where(x => x.FixtureNumber.StartsWith("WS1"))
                            .OrderBy(x => x.ShortenFixtureNumber)
                            .As<Fixture>()
                            .ToList();
    
    var fixture2 = session.Query<Fixture>()
                            .FirstOrDefault(x => x.FixtureNumber == "WS1-1-14-1");
    

    但是,这可能看起来相当复杂,在您的情况下,我认为默认的字符串排序比较器将直接在未更改的 FixtureNumber 上工作,但希望这篇文章对索引的情况提供一些帮助。

    【讨论】:

    • 啊,好吧,这是在哪里记录的吗?我从文档中得到的印象是,在没有索引的情况下查询时会创建一个自动生成的索引。实际上,在我发布解决方法之后,我就实施了您的建议,因为当我使用默认字符串排序比较器的索引属性时,它以错误的顺序对字符串进行排序。
    • 我在原始问题中添加了更多信息,关于当我对相关属性使用默认排序选项时会发生什么。
    • 这是今年早些时候的一篇文章,Ayende 基本上建议了您一直在做的事情,将输出更改为索引:groups.google.com/forum/#!topic/ravendb/2V8Woydz8KQ - 但是,如果您还需要查询该属性,您可能必须在索引中使用两个属性,即原始属性和更改后的属性。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-24
    • 2017-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-22
    相关资源
    最近更新 更多