URL作为RavenDB中的键

时间:2013-02-12 11:33:56

标签: ravendb

在RavenDB中使用URL作为键的最佳方法是什么?

不幸的是,更新项目的语义在文档中并不清楚:如果键以反斜杠结尾,则它始终是插入,否则如果键已经存在则可能是更新。

但是URLs can end up in slash,而RavenDB uses terminating slashes for key generation

  

RavenDB也支持Identity的概念,例如,如果您需要   ID是连续的。通过在您的。中创建字符串Id属性   实体,并将其设置为以斜杠(/)结尾的值,您可以   告诉RavenDB将其用作实体的密钥前缀。那个前缀   然后是下一个可用的整数ID,它将是您的实体   调用SaveChanges()后的ID。   并且无法重新配置正斜杠。所以它并没有真正“支持”它,而是强制执行它。

编辑:相同的RavenDB文档页面声明了以下内容,它与观察到的行为不对应:

  

您可以根据自己的想象为文档分配任何ID。   一切都会正常工作,但你必须要注意   某些ID可能会导致性能问题   具有自定义生成ID的文档非常高(数百万   文档)。

选项包括:  1.修改您的网址以删除结尾斜杠  2. Url编码网址(由RavenDB维护者建议)  3.修改架构并使用数据库生成的ID

在大多数情况下,选项1应该是安全的。选项2会使密钥不可读,而且我还没有设法让它工作(可能是RavenDB或我的代码中的错误)。选项3似乎不必要地使架构复杂化。

一般来说,最好的行动方案是什么?

3 个答案:

答案 0 :(得分:3)

我认为这是一个偏好问题 - 但我不认为URL是非常好的密钥。其他人不同意。请参阅支持论坛上的this discussion

我会认真考虑为什么你需要它作为一个键,如果你可以索引url而不是。例如:

public class Site
{
    public string Id { get; set; } // such as "sites/1"
    public string Name { get; set; }
    public string Url { get; set; }
}

var q = session.Query<Site>().Where(x=> x.Url == "http://foo/bar");

使用它作为关键的论点是URL应该唯一地表示资源,但是当您考虑http与https,可选的查询字符串参数等时,情况并非总是这样。

此外,RavenDB文档密钥不区分大小写,而URL(通常)大小写敏感。许多Web服务器将忽略基本URL上的大小写,但仍然由Web应用程序决定如何区分大小写或对查询字符串参数不敏感。因此,http://foo/bar?q=abchttp://foo/bar?q=ABC完全有可能引用两个不同的资源,但它们将被视为Raven中的相同文档密钥。

如果您认为必须使用URL作为文档密钥,那么正如Ayende所说,您应该以某种方式逃避它们,可能是这样的:

// to escape
var key = Uri.EscapeDataString(url);


// to unescape
var url = Uri.UnescapeDataString(key);

我确信还有其他转义或编码格式也可以使用,这似乎是最简单的。

答案 1 :(得分:1)

如果要将其用作文档密钥,则需要转义URL。

答案 2 :(得分:1)

让我从实践者的角度来看这里。我必须将OpenIds存储为RavenDb中的文档密钥,所以自然会出现这个问题。虽然最近的版本修复了与作为文档密钥的esftped URL相关的问题,但我仍然不能推荐它,因为我已经遇到了各种各样的错误。我报告了其中的一些并且它们已经修复,但我最终放弃了。

我首先开始在URL上使用base64编码,但很快发现这可能导致超过RavenDb限制的长文档密钥,并且您将看到服务器端Esent ColumnTooBig异常。

由于这些ID太长了(法律网址可能是up to 2000 characters),我已经开始使用它们的base64编码SHA-Hashes。不能说它很优雅,但效果很好。