1. 程式人生 > >[原創] RavenDB 安裝 使用

[原創] RavenDB 安裝 使用

RavenDB 安裝/使用

文件極少, 幾乎沒有社群討論, 官網對 HTTP API 的文件幾乎沒有. (版本2.5有一些 HTTP API 文件).
SDK 示例程式碼以 c# 為主, 其餘幾乎為空.
文中測試的 API 都是在瀏覽器 UI 上操作抓包獲取. 有些 API 是靠感覺猜出來的.
到底還是.net寫的 … 安裝目錄就一個 Server 資料夾, 裡面放著所有的 .dll, .so, *.json …
和 couchdb 相比, 易用性好一些. 但從整體上看, 不如 couchdb.

下載/安裝

下載地址: https://ravendb.net/download
支援: WINDOWS, LINUX, MACOS, RASPBERRY PI, DOCKER, NUGET

這裡是在 Macbook 上安裝的

$ wget https://daily-builds.s3.amazonaws.com/RavenDB-4.0.2-osx-x64.tar.bz2
$ tar zxvf RavenDB-4.0.2-osx-x64.tar.bz2
$ cd RavernDB
$ bash run.sh
# 需要安裝 libsodium 模組
# brew install libsodium

啟動/配置

可以看到啟動成功. 預設埠是5984

# 如果沒有異常, 會看到如下提示
Using GC in server concurrent mode retaining memory from the OS.
Could not start browser: No such file or directory
Server available on: http://127.0
.0.1:57606 Tcp listening on 127.0.0.1:57607 Server started, listening to requests... TIP: type 'help' to list the available commands. Running non-interactive. $ curl -v http://127.0.0.1:57606 * Rebuilt URL to: http://127.0.0.1:57606/ * Trying 127.0.0.1... * TCP_NODELAY set * Connected to 127.0.0.1 (127.0.0.1) port 57606
(#0) > GET / HTTP/1.1 > Host: 127.0.0.1:57606 > User-Agent: curl/7.54.0 > Accept: */* > < HTTP/1.1 301 Moved Permanently < Date: Tue, 10 Apr 2018 09:12:44 GMT < Content-Type: application/json; charset=utf-8 < Server: Kestrel < Content-Length: 0 < Location: /studio/index.html < * Connection #0 to host 127.0.0.1 left intact

直接開啟瀏覽器, 訪問控制檯提示的地址, 會引導進行一些配置, 安全配置等等資訊.
在安裝目錄 Server 中,有一個 setting.json, 預設如下

{
    "ServerUrl": "http://127.0.0.1:0",
    "Setup.Mode": "Initial",
    "DataDir": "RavenData"
}

可以替換為如下, 略過引導配置

{
  "DataDir": "RavenData",
  "License.Eula.Accepted": true,
  "Setup.Mode": "Unsecured",
  "Security.UnsecuredAccessAllowed": "PublicNetwork",
  "ServerUrl": "http://127.0.0.1:8080",
  "ServerUrl.Tcp": "tcp://127.0.0.1:38888"
}

ServerUrl 監聽 http 請求
DataDir 配置資料檔案目錄
Setup.Mode 啟動模式
ServerUrl.Tcp 是用於叢集模式節點之間通訊. - Indicates the IP addresses or host addresses with ports and protocols that the server should listen on for incoming TCP connections, are used for inter-node communication

使用測試

測試可以使用瀏覽器直接測試, 這裡不做說明

使用 curl 測試

建立 DB
$ curl -X PUT "http://127.0.0.1:8080/admin/databases?name=td&replicationFactor=1" -d '{"DatabaseName":"td"}'

{
    "RaftCommandIndex": 19,
    "Name": "td",
    "Topology": {
        "Members": [
            "A"
        ],
        "Promotables": [],
        "Rehabs": [],
        "Stamp": {
            "Index": -1,
            "Term": 1,
            "LeadersTicks": 113011146
        },
        "PromotablesStatus": {},
        "DemotionReasons": {},
        "DynamicNodesDistribution": false,
        "ReplicationFactor": 1
    },
    "NodesAddedTo": [
        "http://127.0.0.1:8080"
    ]
}
$ curl -X PUT "http://127.0.0.1:8080/admin/databases?name=td&replicationFactor=1" -d '{
    "DatabaseName": "td",
    "Settings": {
        "DataDir": null
    },
    "Disabled": false,
    "Encrypted": false,
    "Topology": {
        "DynamicNodesDistribution": false
    }
}'

{"Url":"/admin/databases?name=td&replicationFactor=1","Type":"Raven.Client.Exceptions.ConcurrencyException","Message":"Database 'td' already exists!","Error":"Raven.Client.Exceptions.ConcurrencyException: Database 'td' already exists!\n   at Raven.Server.Web.System.AdminDatabasesHandler.<CreateDatabase>d__6.MoveNext() in C:\\Builds\\RavenDB-Stable-4.0\\src\\Raven.Server\\Web\\System\\AdminDatabasesHandler.cs:line 326\n--- End of stack trace from previous location where exception was thrown ---\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\n   at Raven.Server.Web.System.AdminDatabasesHandler.<Put>d__4.MoveNext() in C:\\Builds\\RavenDB-Stable-4.0\\src\\Raven.Server\\Web\\System\\AdminDatabasesHandler.cs:line 233\n--- End of stack trace from previous location where exception was thrown ---\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\n   at Raven.Server.Routing.RequestRouter.<HandlePath>d__6.MoveNext() in C:\\Builds\\RavenDB-Stable-4.0\\src\\Raven.Server\\Routing\\RequestRouter.cs:line 104\n--- End of stack trace from previous location where exception was thrown ---\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\n   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()\n   at System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult()\n   at Raven.Server.RavenServerStartup.<RequestHandler>d__11.MoveNext() in C:\\Builds\\RavenDB-Stable-4.0\\src\\Raven.Server\\RavenServerStartup.cs:line 159"}
支援 revision
# 檢視當前資料庫配置的 revision
$ curl http://127.0.0.1:8080/databases/qa/revisions/config
{
    "Default": null,
    "Collections": {
        "@empty": {
            "Disabled": false,
            "MinimumRevisionsToKeep": null,
            "MinimumRevisionAgeToKeep": null,
            "PurgeOnDelete": false
        }
    }
}
# 配置 revision
curl -XPOST http://127.0.0.1:8080/databases/qa/admin/revisions/config -d '{
    "Collections": {
        "@empty": {
            "Disabled": false,
            "MinimumRevisionsToKeep": 100,
            "MinimumRevisionAgeToKeep": null,
            "PurgeOnDelete": false
        }
    }
}'

{"RaftCommandIndex":21}

Disabled, true: 關閉 revision, false: 開啟 revision.
MinimumRevisionsToKeep: 保留最近多少個版本, 可以設定為 null
MinimumRevisionAgeToKeep: 保留最近多少天的版本, 可以設定為 null
PurgeOnDelete: 刪除的時候是否徹底清除. 建議 false

新增記錄時, 如果不指定 @[email protected], 會預設新增到 @empty collection
RavenDB 預設不支援 revision, 需要手動開啟. revision 作用域是某個 database 中的 collection

特別注意: 配置 revision 時, 會覆蓋原先的設定, 所以每次提交都必須將以前設定的 revision 也新增進去. 否則會丟失原先的配置.

新增一條記錄 (_id 可以自己定義, 也可以不填, 會預設生成 GUID)
$ curl -XPUT "http://127.0.0.1:8080/databases/qa/docs?id=1" -d '{"name": "zhipeng"}'
{"Id":"1","ChangeVector":"A:22-5YM16pKww0W6G+UxDC7ViQ"}
$ curl -XPUT "http://127.0.0.1:8080/databases/qa/docs?id=2" -d '{
    "name": "zhipeng",
    "@metadata": {},
    "books":["aa", "bb"],
    "school": [{"type": "h", "name": "high school"}, {"type": "u", "name": "university"}],
    "other": {"age": 18, "first_name": "zhang"},
    "desc": "hello world."
}'

{"Id":"2","ChangeVector":"A:42-5YM16pKww0W6G+UxDC7ViQ"}

# 也可以使用 bulk 操作
# 插入一條 id 為2的, 裡面包含 list, dictionary 兩種型別. ["", ""], [{}, {}], {}
$ curl -XPOST http://127.0.0.1:8080/databases/qa/bulk_docs -d '{
    "Commands": [
        {
            "Document": {
                "info": {
                    "a": 123,
                    "b": 456
                },
                "name": "zhipeng",
                "@metadata": {
                    "@collection": "qa",
                    "@id": ""
                }
            },
            "Id": "",
            "Type": "PUT"
        },
        {
            "Document": {
                "name": "zhipeng",
                "books": [
                    "aa",
                    "bb"
                ],
                "school": [
                    {
                        "type": "h",
                        "name": "high school"
                    },
                    {
                        "type": "u",
                        "name": "university"
                    }
                ],
                "other": {
                    "age": 18,
                    "first_name": "zhang"
                },
                "desc": "hello world.",
                "@metadata": {
                    "@id": "2"
                }
            },
            "Id": "2",
            "Type": "PUT"
        }
    ]
}'

{
    "Results": [
        {
            "Type": "PUT",
            "@id": "2",
            "@collection": "@empty",
            "@change-vector": "A:42-5YM16pKww0W6G+UxDC7ViQ",
            "@last-modified": "2018-04-10T11:41:17.1278590",
            "@flags": "HasRevisions"
        },
        {
            "Type": "PUT",
            "@id": "269639cf-0852-430c-b256-3cdee38b2519",
            "@collection": "qa",
            "@change-vector": "A:14-5YM16pKww0W6G+UxDC7ViQ",
            "@last-modified": "2018-04-10T10:27:33.9939300",
            "@flags": "HasRevisions"
        }
    ]
}

$ curl -XPUT "http://127.0.0.1:8080/databases/qa/docs" -d '{"name": "zhipeng"}'
{"Url":"/databases/qa/docs?id=%20","Type":"System.ArgumentException","Message":"Query string value 'id' must have a non empty value","Error":"System.ArgumentException: Query string value 'id' must have a non empty value\n   at Raven.Server.Web.RequestHandler.InvalidEmptyValue(String name) in C:\\Builds\\RavenDB-Stable-4.0\\src\\Raven.Server\\Web\\RequestHandler.cs:line 341\n   at Raven.Server.Web.RequestHandler.GetQueryStringValueAndAssertIfSingleAndNotEmpty(String name) in C:\\Builds\\RavenDB-Stable-4.0\\src\\Raven.Server\\Web\\RequestHandler.cs:line 333\n   at Raven.Server.Documents.Handlers.DocumentHandler.<Put>d__7.MoveNext() in C:\\Builds\\RavenDB-Stable-4.0\\src\\Raven.Server\\Documents\\Handlers\\DocumentHandler.cs:line 240\n--- End of stack trace from previous location where exception was thrown ---\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\n   at Raven.Server.Routing.RequestRouter.<HandlePath>d__6.MoveNext() in C:\\Builds\\RavenDB-Stable-4.0\\src\\Raven.Server\\Routing\\RequestRouter.cs:line 97\n--- End of stack trace from previous location where exception was thrown ---\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\n   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()\n   at System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult()\n   at Raven.Server.RavenServerStartup.<RequestHandler>d__11.MoveNext() in C:\\Builds\\RavenDB-Stable-4.0\\src\\Raven.Server\\RavenServerStartup.cs:line 159"}

如果不使用 bulk, 必須指定 id, 否則無法自動生成 id.

查詢 - 獲取所有記錄
$ curl  "http://127.0.0.1:8080/databases/qa/docs?start=0&pageSize=10"

{
    "Results": [
        {
            "name": "zhipeng",
            "@metadata": {
                "@change-vector": "A:40-5YM16pKww0W6G+UxDC7ViQ",
                "@flags": "HasRevisions",
                "@id": "1",
                "@last-modified": "2018-04-10T11:29:39.6150230Z"
            }
        },
        {
            "name": "zhipeng",
            "desc": "test collection.x'x'x",
            "@metadata": {
                "@collection": "qa",
                "@change-vector": "A:12-5YM16pKww0W6G+UxDC7ViQ",
                "@flags": "HasRevisions",
                "@id": "zhipeng",
                "@last-modified": "2018-04-10T09:41:57.0446820Z"
            }
        }
    ]
}

# 也可以用這個 API, 可以返回查詢到的資料所包含的欄位
curl "http://127.0.0.1:8080/databases/qa/studio/collections/preview?start=0&pageSize=10"

{
    "Results": [
        {
            "@metadata": {
                "$a": [],
                "$o": [],
                "$t": [],
                "@change-vector": "A:40-5YM16pKww0W6G+UxDC7ViQ",
                "@flags": "HasRevisions",
                "@id": "1",
                "@last-modified": "2018-04-10T11:29:39.6150230Z"
            }
        },
        {
            "@metadata": {
                "$a": [],
                "$o": [],
                "$t": [],
                "@collection": "qa",
                "@change-vector": "A:12-5YM16pKww0W6G+UxDC7ViQ",
                "@flags": "HasRevisions",
                "@id": "zhipeng",
                "@last-modified": "2018-04-10T09:41:57.0446820Z"
            }
        }
    ],
    "TotalResults": 2,
    "AvailableColumns": [
        "name",
        "desc"
    ]
}
查詢 - 根據 id 查詢
$ curl  "http://127.0.0.1:8080/databases/qa/docs?id=1"
{
    "Results": [
        {
            "name": "zhipeng",
            "@metadata": {
                "@change-vector": "A:40-5YM16pKww0W6G+UxDC7ViQ",
                "@flags": "HasRevisions",
                "@id": "1",
                "@last-modified": "2018-04-10T11:29:39.6150230Z"
            }
        }
    ],
    "Includes": {}
}
$ curl  "http://127.0.0.1:8080/databases/qa/docs?id=2&id=1" 
{
    "Results": [
        {
            "name": "zhipeng",
            "books": [
                "aa",
                "bb"
            ],
            "school": [
                {
                    "type": "h",
                    "name": "high school"
                },
                {
                    "type": "u",
                    "name": "university"
                }
            ],
            "other": {
                "age": 18,
                "first_name": "zhang"
            },
            "desc": "hello world.",
            "@metadata": {
                "@change-vector": "A:42-5YM16pKww0W6G+UxDC7ViQ",
                "@flags": "HasRevisions",
                "@id": "2",
                "@last-modified": "2018-04-10T11:41:17.1278590Z"
            }
        },
        {
            "name": "zhipeng",
            "@metadata": {
                "@change-vector": "A:40-5YM16pKww0W6G+UxDC7ViQ",
                "@flags": "HasRevisions",
                "@id": "1",
                "@last-modified": "2018-04-10T11:29:39.6150230Z"
            }
        }
    ],
    "Includes": {}
}
# 等同下面的效果
$ curl -XPOST "http://127.0.0.1:8080/databases/qa/docs" -d '{"Ids":[2,1, "zhipeng"]}'

如果需要查詢多個 id, 可以在引數中拼接. 例如 id=1&id=2

查詢 - 查詢語法

RavenDB 將 SQL 稱之為 RQL. 後面 RQL 都用 SQL 表示.
查詢地址: /databases/qa/queries?query=SQL&start=0&pageSize=10
平常的 SQL 是 select fields from TABLE where WHERE\_SYNTAX;
RavenDB SQL 稍有不同, 是 from TABLE where WHERE\_SYNTAX select fields

注意行尾不要加 ;

$ curl "http://127.0.0.1:8080/databases/qa/queries?query=from%20qa%20%20%0D%0Awhere%20name%20%3D%20%22zhipeng%22%0D%0Aselect%20ID()%20as%20id%2C%20name&start=0&pageSize=10"

{
    "TotalResults": 2,
    "SkippedResults": 0,
    "DurationInMs": 0,
    "IncludedPaths": null,
    "IndexName": "Auto/qa/Bybooks.CountAndbooks[]AndnameAndother.ageAndschool[].type",
    "Results": [
        {
            "id": "zhipeng",
            "name": "zhipeng",
            "@metadata": {
                "@projection": true,
                "@change-vector": "A:12-5YM16pKww0W6G+UxDC7ViQ",
                "@flags": "HasRevisions",
                "@id": "zhipeng",
                "@index-score": 0.594534814357758,
                "@last-modified": "2018-04-10T09:41:57.0446820Z"
            }
        },
        {
            "id": "2",
            "name": "zhipeng",
            "@metadata": {
                "@projection": true,
                "@change-vector": "A:52-5YM16pKww0W6G+UxDC7ViQ",
                "@id": "2",
                "@index-score": 0.594534814357758,
                "@last-modified": "2018-04-11T03:04:48.1657180Z"
            }
        }
    ],
    "Includes": {},
    "IndexTimestamp": "2018-04-11T04:06:00.7646740",
    "LastQueryTime": "2018-04-11T04:17:41.3646580",
    "IsStale": false,
    "ResultEtag": -6847100035392847000
}

後面只寫 SQL, 不再寫 curl, 將 SQL 用 urlEncode 後放入引數 query 即可

基礎查詢
from qa where name = "zhipeng" select ID() as id, name
from qa group by name where name = "zhipeng" select name, count() as count

需要注意, 不能直接使用如果要使用 COUNT(), 必須使用聚合函式.
主鍵 id 必須使用 ID() 才可以正常返回. 否則只能從 @metadata 中獲取

list 相關查詢
from qa where books.Count = 2 select books, ID() as ID
// 這裡是可以使用一部分 js 語法的
from qa where books.length = 2 select books, ID() as ID

SQL: from qa as c where c.books.length = 2 select { book: c.books, metadata: c["@metadata"], _source: c, id: c["@metadata"]["@id"]}


// 查詢 books 中存在 "aa" 這本書的所有記錄
from qa where books[] = "aa" select *
//result
{
    "TotalResults": 1,
    "SkippedResults": 0,
    "DurationInMs": 0,
    "IncludedPaths": null,
    "IndexName": "Auto/qa/Bybooks.CountAndbooks[]",
    "Results": [
        {
            "name": "zhipeng",
            "books": [
                "aa",
                "bb"
            ],
            "school": [
                {
                    "type": "h",
                    "name": "high school"
                },
                {
                    "type": "u",
                    "name": "university"
                }
            ],
            "other": {
                "age": 18,
                "first_name": "zhang"
            },
            "desc": "hello world.",
            "@metadata": {
                "@collection": "qa",
                "@change-vector": "A:52-5YM16pKww0W6G+UxDC7ViQ",
                "@id": "2",
                "@index-score": 0.3068528175354,
                "@last-modified": "2018-04-11T03:04:48.1657180Z"
            }
        }
    ],
    "Includes": {},
    "IndexTimestamp": "2018-04-11T03:45:00.7649240",
    "LastQueryTime": "2018-04-11T03:59:53.3999770",
    "IsStale": false,
    "ResultEtag": 3604079527690140700
}
dictionary 查詢
from qa where other.age=18 select ID() as id, name, other.age as age
// 查詢上過高中的人名
from qa where school.type  = 'h' select name

需要注意, 如果使用 js 語法查詢, 是沒有辦法獲取到 id 的, 從能後續從@ metadata 中獲取. 不知道是 bug 還是原因. 如果直接獲取這行記錄, 是可以看到@[email protected] 的, 但如果直接獲取[“@metadata”]只能看到@ collection. 所以 id 也就無法獲取.
並且試了 load 語法, 似乎也不行, 獲取不到結果. 可能是 bug 吧, 用不到這個, 所以不細研究了.

from qa as q
load q.other as o
select {
    name: q.name.toUpperCase(),
    other: o.age,
    bookCount: q.books.length
}
// result
{
    "TotalResults": 2,
    "SkippedResults": 0,
    "DurationInMs": 0,
    "IncludedPaths": null,
    "IndexName": "collection/qa",
    "Results": [
        {
            "name": "ZHIPENG",
            "other": null,
            "bookCount": null,
            "q": {
                "@collection": "qa"
            },
            "@metadata": {
                "@projection": true,
                "@change-vector": "A:12-5YM16pKww0W6G+UxDC7ViQ",
                "@flags": "HasRevisions",
                "@id": "zhipeng",
                "@index-score": 0,
                "@last-modified": "2018-04-10T09:41:57.0446820Z"
            }
        },
        {
            "name": "ZHIPENG",
            "other": null,
            "bookCount": 2,
            "q": {
                "@collection": "qa"
            },
            "@metadata": {
                "@projection": true,
                "@change-vector": "A:52-5YM16pKww0W6G+UxDC7ViQ",
                "@id": "2",
                "@index-score": 0,
                "@last-modified": "2018-04-11T03:04:48.1657180Z"
            }
        }
    ],
    "Includes": {},
    "IndexTimestamp": "0001-01-01T00:00:00.0000000",
    "LastQueryTime": "0001-01-01T00:00:00.0000000",
    "IsStale": false,
    "ResultEtag": 6893458203660772000
}
更新
更新記錄和插入記錄介面一樣, 已存在的記錄會自己做版本管理

更新的時候, @metadata 和原記錄保持一致. @collection 不可以更改.

刪除
$ curl -XDELETE "http://127.0.0.1:8080/databases/qa/docs?id=1"

# 也可以使用 bulk 進行批量刪除, 
$ curl -X POST http://127.0.0.1:8080/databases/qa/bulk_docs -d '{"Commands":[{"Id":"0910b0f3-3878-4667-811f-3c0cff067f44","Type":"DELETE"},{"Id":"269639cf-0852-430c-b256-3cdee38b2519","Type":"DELETE"}]}'
{
    "Results": [
        {
            "Id": "0910b0f3-3878-4667-811f-3c0cff067f44",
            "Type": "DELETE",
            "Deleted": true
        },
        {
            "Id": "269639cf-0852-430c-b256-3cdee38b2519",
            "Type": "DELETE",
            "Deleted": true
        }
    ]
}

刪除的時候不需要指定版本號, couchdb 必須指定.
刪除只是刪除當前版本, 並且會生成出一個被刪除的版本. 舊版本是可以繼續查到的.
如果再建立一條記錄, _id 存在過, 版本號會在最後一次刪除的版本基礎上 +1.

檢視版本記錄
$ curl "http://127.0.0.1:8080/databases/qa/revisions?id=1&start=0&pageSize=100&metadataOnly=false"
{
    "Results": [
        {
            "name": "11",
            "desc": "1",
            "@metadata": {
                "@collection": "qa",
                "@change-vector": "A:58-5YM16pKww0W6G+UxDC7ViQ",
                "@flags": "HasRevisions, Revision",
                "@id": "1",
                "@last-modified": "2018-04-11T06:50:46.7506050Z"
            }
        },
        {
            "@metadata": {
                "@collection": "@empty",
                "@change-vector": "A:53-5YM16pKww0W6G+UxDC7ViQ",
                "@flags": "HasRevisions, DeleteRevision",
                "@id": "1",
                "@last-modified": "2018-04-11T06:48:46.4398030Z"
            }
        },
        {
            "Name": "...",
            "@metadata": {
                "@change-vector": "A:36-5YM16pKww0W6G+UxDC7ViQ",
                "@flags": "HasRevisions, Revision",
                "@id": "1",
                "@last-modified": "2018-04-10T10:45:11.6156140Z"
            }
        },
        {
            "name": "zhipeng",
            "id": "1",
            "@metadata": {
                "@change-vector": "A:16-5YM16pKww0W6G+UxDC7ViQ",
                "@flags": "HasRevisions, Revision",
                "@id": "1",
                "@last-modified": "2018-04-10T10:36:22.3838210Z"
            }
        }
    ],
    "TotalResults": 11
}

metadataOnly=true 只返回 metadata 資訊. 預設為 false

檢視某個版本記錄
$ curl "http://127.0.0.1:8080/databases/qa/revisions?changeVector=A%3A58-5YM16pKww0W6G%2BUxDC7ViQ"
{
    "Results": [
        {
            "name": "11",
            "desc": "1",
            "@metadata": {
                "@collection": "qa",
                "@change-vector": "A:58-5YM16pKww0W6G+UxDC7ViQ",
                "@flags": "HasRevisions, Revision",
                "@id": "1",
                "@last-modified": "2018-04-11T06:50:46.7506050Z"
            }
        }
    ]
}

檢視某條記錄的某個版本, 只需要用 @change-vector 即可, 不需要 id.
特別注意, 某條記錄如果已經設定了 collection, 是不能再更換 collection 的. 即使第一次是 @empty, 也不能更換.

如果想更換 collection, 只能將其刪除, 重新建立, 並指定 collection.
切換過 collection 的資料, 短時間內不能再刪除, 只能更新. 比如上面 id=1 的 revision, collection 就是從 @empty 切換到 qa, 繼續操作刪除, 就會報錯.

$ curl POST http://127.0.0.1:8080/databases/qa/bulk_docs -d '{"Commands":[{"Id":"1","Type":"DELETE","ChangeVector":null}]}'
$ curl -v -XDELETE "http://127.0.0.1:8080/databases/qa/docs?id=1"

Voron.Exceptions.ConcurrencyException: Value already exists, but requested NewOnly

{"Url":"/databases/qa/bulk_docs","Type":"Voron.Exceptions.ConcurrencyException","Message":"Value already exists, but requested NewOnly","Error":"Voron.Exceptions.ConcurrencyException: Value already exists, but requested NewOnly\n   at Voron.Data.BTrees.Tree.ThrowConcurrencyException() in C:\\Builds\\RavenDB-Stable-4.0\\src\\Voron\\Data\\BTrees\\Tree.cs:line 411\n   at Voron.Data.BTrees.Tree.DirectAdd(Slice key, Int32 len, TreeNodeFlags nodeType, Byte*& ptr) in C:\\Builds\\RavenDB-Stable-4.0\\src\\Voron\\Data\\BTrees\\Tree.cs:line 292\n   at Voron.Data.Tables.Table.InsertIndexValuesFor(Int64 id, TableValueReader& value) in C:\\Builds\\RavenDB-Stable-4.0\\src\\Voron\\Data\\Tables\\Table.cs:line 611\n   at Voron.Data.Tables.Table.Insert(TableValueBuilder builder) in C:\\Builds\\RavenDB-Stable-4.0\\src\\Voron\\Data\\Tables\\Table.cs:line 479\n   at Raven.Server.Documents.DocumentsStorage.CreateTombstone(DocumentsOperationContext context, Slice lowerId, Int64 documentEtag, CollectionName collectionName, String docChangeVector, Int64 lastModifiedTicks, String changeVector, DocumentFlags flags) in C:\\Builds\\RavenDB-Stable-4.0\\src\\Raven.Server\\Documents\\DocumentsStorage.cs:line 1320\n   at Raven.Server.Documents.DocumentsStorage.Delete(DocumentsOperationContext context, Slice lowerId, String id, LazyStringValue expectedChangeVector, Nullable`1 lastModifiedTicks, String changeVector, CollectionName collectionName, NonPersistentDocumentFlags nonPersistentFlags, DocumentFlags documentFlags) in C:\\Builds\\RavenDB-Stable-4.0\\src\\Raven.Server\\Documents\\DocumentsStorage.cs:line 1129\n   at Raven.Server.Documents.DocumentsStorage.Delete(DocumentsOperationContext context, String id, String expectedChangeVector) in C:\\Builds\\RavenDB-Stable-4.0\\src\\Raven.Server\\Documents\\DocumentsStorage.cs:line 1028\n   at Raven.Server.Documents.Handlers.BatchHandler.MergedBatchCommand.Execute(DocumentsOperationContext context) in C:\\Builds\\RavenDB-Stable-4.0\\src\\Raven.Server\\Documents\\Handlers\\BatchHandler.cs:line 305\n--- End of stack trace from previous location where exception was thrown ---\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\n   at Raven.Server.Documents.Handlers.BatchHandler.<BulkDocs>d__0.MoveNext() in C:\\Builds\\RavenDB-Stable-4.0\\src\\Raven.Server\\Documents\\Handlers\\BatchHandler.cs:line 59\n--- End of stack trace from previous location where exception was thrown ---\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\n   at Raven.Server.Routing.RequestRouter.<HandlePath>d__6.MoveNext() in C:\\Builds\\RavenDB-Stable-4.0\\src\\Raven.Server\\Routing\\RequestRouter.cs:line 97\n--- End of stack trace from previous location where exception was thrown ---\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\n   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()\n   at System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult()\n   at Raven.Server.RavenServerStartup.<RequestHandler>d__11.MoveNext() in C:\\Builds\\RavenDB-Stable-4.0\\src\\Raven.Server\\RavenServerStartup.cs:line 159"}

大概2分鐘左右, 就可以刪除成功. 應該是資料同步有一定延時造成的.

通過這個現象, 我認為 RavenDB collection 不等同於 mongodb 中的 collection, mongodb 中的 collection 可以理解為傳統資料庫中的 table, 但 RavenDB 中, 應該將 database 理解為表.

參考

相關推薦

[原創] RavenDB 安裝 使用

RavenDB 安裝/使用 文件極少, 幾乎沒有社群討論, 官網對 HTTP API 的文件幾乎沒有. (版本2.5有一些 HTTP API 文件). SDK 示例程式碼以 c# 為主, 其餘幾乎為空. 文中測試的 API 都是在瀏覽器 UI 上操作抓

[原創]OpenvSwitch安裝

源碼編譯 bit 數據庫 sch private usr ger 模式 linu 一、安裝環境: ubuntu-12.04-64bit 二、使用root權限,安裝所需軟件: apt-get install build-essential apt-get install op

[原創]mininet安裝

運行 源碼安裝 shark pin nap 默認 12.1 director reference mininet安裝: on Ubuntu 13.04: sudo apt-get install minineton Ubuntu 12.10: sudo apt-get in

[原創]CentOS7安裝遠程工具teamviewer12

圖片 processor .rpm rpm clas pass ces 環境 重置密碼 系統環境:CentOS 7.0.1 1.下載安裝# wget https://dl.tvcdn.de/download/version_12x/teamviewer_12.0.85001

[原創]macOS安裝wget

mac用了一年多,今天使用wget命令,竟然提示命令不存在。只好下載原始碼進行安裝了。 安裝過程有點曲折: 編譯wget時,提示pkg-config不存在 第一次從git上下載了pkg-config的原始碼,雖然注意到檔名為pkg-config-pkg-config-0.29.2.tar.gz,而

原創安裝ODAC後,PL/SQL連線提…

問題描述:     安裝ODAC後,用PL/SQL登入測試原有的資料庫,先是提示:access violation ataddress....,重啟監聽後又     提示“TNS:無法解析指定的連線識別符號”錯誤。  原因分析:      因為同事也裝過一次,說是不能與oracle客戶端裝在同一個目錄下。但

原創 Spark動手實踐 1】Hadoop2.7.3安裝部署實際動手

dmi 遠程 nag proc host 一個 error img 連接 目錄: 第一部分:操作系統準備工作:   1. 安裝部署CentOS7.3 1611   2. CentOS7軟件安裝(net-tools, wget, vim等)   3. 更新CentOS

[原創]MacPro上使用VMware Fusion安裝CentOS7 minimal版

x86_64 什麽 mdk cnblogs art 連接 安裝過程 普通用戶 大小 MacPro上使用VMware Fusion安裝CentOS7 minimal版 版權聲明:本文為博主原創文章,轉載請註明出處。 一.系統環境 macPro: VMware Fu

原創】使用workstation安裝Xenserver 6.5+cloudstack 4.10----本地存儲模式

登錄 queue alt ast rim 4.0 個人學習 white 配置 1. 背景: 近期由於項目和個人學習得需求,開始接觸到Cloudstack,雖然雲計算概念在大學剛畢業的時候就已經略有耳聞,但是由於工作原因,也一直沒有了解,下班後想自己折騰下cloudstac

[原創]在Centos7.2上源碼安裝PHP、Nginx、Zentao禪道

session zip nss markdown src roo -perm mbstring 復制 版本 操作系統:CentOS Linux release 7.2.1511 (Core) PHP:5.6.33 Nginx:1.12.2 MySQL:5.6.38(192

Jetson TX2安裝固態硬盤(原創

src dia image mat 查看系統 orm alt ron ets SSD on Jetson TX2 註意事項:在斷電情況下,將固態硬盤的接線與Jetson TX2進行連接 步驟: 一、jetson tx2開機,打開搜索欄中的Disks 二、Disks

Linux安裝mysql(Redhat6.5+MySQL5.7)(轉載+原創補漏)

controls 新版 file grep gin leg 下載 set CP 這裏我創建了一目錄software用於存放我們待會要下載的mysql包,先去到該目錄 命令:cd /software命令:wget http://mirrors.sohu.com/mysql/M

(趙強老師原創)搭建CDH實驗環境,三個節點的安裝配置

大數據 CDH 安裝配置 Hadoop Spark 趙強老師簡介-------------------------------------------------------清華大學軟件工程專業畢業。現就職於Oracle(中國)有限公司高級技術顧問,在Oracle公司服務已超過10年。業界

[原創]X-HDL 4.2安裝與使用

由於涉及到VHDL工程,但實際工作中,用Verilog更多些,因此安裝X-HDL進行轉換,安裝步驟與使用如下: X-HDL進行破解,破解如下: 安裝完畢後,開啟一個帶轉換的檔案,進行如下操作: 連結:https://pan.baidu.com/s/

[樂意黎原創]Centos主機動態安裝PHP的bcmath,Libmcrypt,mhash,mcrypt等擴充套件模組方法

如下,Centos裡啟動 php-fpm 時,控制檯總在拋若干警告。 [[email protected]] #service php-fpm start Starting php-fpm daemon is success[28-Nov-2018 17:45:40] NOTIC

最新原創個人實踐總結安裝CocoaPods方法詳解

首先升級Ruby環境,終端輸入:gem update --system,會出現兩種情況, 1,Latest version already installed. Done. 說明已經最新 2,沒許可權升級Ruby的提示,這是因為你沒有許可權去升級Ruby 這時應該輸

zzw原創_非root安裝fastDFS

zzw原創_非root安裝fastDFS fastDFS 想要非root安裝,沒找到資料,分析了一下安裝指令碼,原來作者是留了安裝路徑的,但沒有放出來。   1、解包 [[email protected] setup]$ tar  -xvf  libfastco

原創Linux Centos6.9 安裝Oracle11G R2

純原創手敲 累吐血。。。。。。,詳情檢視附件rar中的word(內有命令操作截圖)       1. 解除安裝先檢視 rpm -qa | grep java   rpm -e --nodeps java-1.4.2-g

VS2005下編譯、安裝Net-snmp 5.4.1.2手記(原創

VS2005下編譯、安裝Net-snmp 5.4.1.2手記 by Flyfish <[email protected]>2008-09-08:=======================================================

[原創]Homestead 開發環境安裝筆記

Vagrant 安裝 Homestead 筆記 參考文章: 1. 預先準備 命令列 說明 vagrant init 初始化 vagrant vagrant up 啟動 vagrant