]>
Commit | Line | Data |
---|---|---|
7c673cae | 1 | // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. |
11fdf7f2 TL |
2 | // This source code is licensed under both the GPLv2 (found in the |
3 | // COPYING file in the root directory) and Apache 2.0 License | |
4 | // (found in the LICENSE.Apache file in the root directory). | |
7c673cae FG |
5 | |
6 | #pragma once | |
7 | #ifndef ROCKSDB_LITE | |
8 | ||
9 | #include <string> | |
10 | #include <vector> | |
11 | ||
12 | #include "rocksdb/utilities/stackable_db.h" | |
13 | #include "rocksdb/utilities/json_document.h" | |
14 | #include "rocksdb/db.h" | |
15 | ||
16 | namespace rocksdb { | |
17 | ||
18 | // IMPORTANT: DocumentDB is a work in progress. It is unstable and we might | |
19 | // change the API without warning. Talk to RocksDB team before using this in | |
20 | // production ;) | |
21 | ||
22 | // DocumentDB is a layer on top of RocksDB that provides a very simple JSON API. | |
23 | // When creating a DB, you specify a list of indexes you want to keep on your | |
24 | // data. You can insert a JSON document to the DB, which is automatically | |
25 | // indexed. Every document added to the DB needs to have "_id" field which is | |
26 | // automatically indexed and is an unique primary key. All other indexes are | |
27 | // non-unique. | |
28 | ||
29 | // NOTE: field names in the JSON are NOT allowed to start with '$' or | |
30 | // contain '.'. We don't currently enforce that rule, but will start behaving | |
31 | // badly. | |
32 | ||
33 | // Cursor is what you get as a result of executing query. To get all | |
34 | // results from a query, call Next() on a Cursor while Valid() returns true | |
35 | class Cursor { | |
36 | public: | |
37 | Cursor() = default; | |
38 | virtual ~Cursor() {} | |
39 | ||
40 | virtual bool Valid() const = 0; | |
41 | virtual void Next() = 0; | |
42 | // Lifecycle of the returned JSONDocument is until the next Next() call | |
43 | virtual const JSONDocument& document() const = 0; | |
44 | virtual Status status() const = 0; | |
45 | ||
46 | private: | |
47 | // No copying allowed | |
48 | Cursor(const Cursor&); | |
49 | void operator=(const Cursor&); | |
50 | }; | |
51 | ||
52 | struct DocumentDBOptions { | |
53 | int background_threads = 4; | |
54 | uint64_t memtable_size = 128 * 1024 * 1024; // 128 MB | |
55 | uint64_t cache_size = 1 * 1024 * 1024 * 1024; // 1 GB | |
56 | }; | |
57 | ||
58 | // TODO(icanadi) Add `JSONDocument* info` parameter to all calls that can be | |
59 | // used by the caller to get more information about the call execution (number | |
60 | // of dropped records, number of updated records, etc.) | |
61 | class DocumentDB : public StackableDB { | |
62 | public: | |
63 | struct IndexDescriptor { | |
64 | // Currently, you can only define an index on a single field. To specify an | |
65 | // index on a field X, set index description to JSON "{X: 1}" | |
66 | // Currently the value needs to be 1, which means ascending. | |
67 | // In the future, we plan to also support indexes on multiple keys, where | |
68 | // you could mix ascending sorting (1) with descending sorting indexes (-1) | |
69 | JSONDocument* description; | |
70 | std::string name; | |
71 | }; | |
72 | ||
73 | // Open DocumentDB with specified indexes. The list of indexes has to be | |
74 | // complete, i.e. include all indexes present in the DB, except the primary | |
75 | // key index. | |
76 | // Otherwise, Open() will return an error | |
77 | static Status Open(const DocumentDBOptions& options, const std::string& name, | |
78 | const std::vector<IndexDescriptor>& indexes, | |
79 | DocumentDB** db, bool read_only = false); | |
80 | ||
81 | explicit DocumentDB(DB* db) : StackableDB(db) {} | |
82 | ||
83 | // Create a new index. It will stop all writes for the duration of the call. | |
84 | // All current documents in the DB are scanned and corresponding index entries | |
85 | // are created | |
86 | virtual Status CreateIndex(const WriteOptions& write_options, | |
87 | const IndexDescriptor& index) = 0; | |
88 | ||
89 | // Drop an index. Client is responsible to make sure that index is not being | |
90 | // used by currently executing queries | |
91 | virtual Status DropIndex(const std::string& name) = 0; | |
92 | ||
93 | // Insert a document to the DB. The document needs to have a primary key "_id" | |
94 | // which can either be a string or an integer. Otherwise the write will fail | |
95 | // with InvalidArgument. | |
96 | virtual Status Insert(const WriteOptions& options, | |
97 | const JSONDocument& document) = 0; | |
98 | ||
99 | // Deletes all documents matching a filter atomically | |
100 | virtual Status Remove(const ReadOptions& read_options, | |
101 | const WriteOptions& write_options, | |
102 | const JSONDocument& query) = 0; | |
103 | ||
104 | // Does this sequence of operations: | |
105 | // 1. Find all documents matching a filter | |
106 | // 2. For all documents, atomically: | |
107 | // 2.1. apply the update operators | |
108 | // 2.2. update the secondary indexes | |
109 | // | |
110 | // Currently only $set update operator is supported. | |
111 | // Syntax is: {$set: {key1: value1, key2: value2, etc...}} | |
112 | // This operator will change a document's key1 field to value1, key2 to | |
113 | // value2, etc. New values will be set even if a document didn't have an entry | |
114 | // for the specified key. | |
115 | // | |
116 | // You can not change a primary key of a document. | |
117 | // | |
118 | // Update example: Update({id: {$gt: 5}, $index: id}, {$set: {enabled: true}}) | |
119 | virtual Status Update(const ReadOptions& read_options, | |
120 | const WriteOptions& write_options, | |
121 | const JSONDocument& filter, | |
122 | const JSONDocument& updates) = 0; | |
123 | ||
124 | // query has to be an array in which every element is an operator. Currently | |
125 | // only $filter operator is supported. Syntax of $filter operator is: | |
126 | // {$filter: {key1: condition1, key2: condition2, etc.}} where conditions can | |
127 | // be either: | |
128 | // 1) a single value in which case the condition is equality condition, or | |
129 | // 2) a defined operators, like {$gt: 4}, which will match all documents that | |
130 | // have key greater than 4. | |
131 | // | |
132 | // Supported operators are: | |
133 | // 1) $gt -- greater than | |
134 | // 2) $gte -- greater than or equal | |
135 | // 3) $lt -- less than | |
136 | // 4) $lte -- less than or equal | |
137 | // If you want the filter to use an index, you need to specify it like this: | |
138 | // {$filter: {...(conditions)..., $index: index_name}} | |
139 | // | |
140 | // Example query: | |
141 | // * [{$filter: {name: John, age: {$gte: 18}, $index: age}}] | |
142 | // will return all Johns whose age is greater or equal to 18 and it will use | |
143 | // index "age" to satisfy the query. | |
144 | virtual Cursor* Query(const ReadOptions& read_options, | |
145 | const JSONDocument& query) = 0; | |
146 | }; | |
147 | ||
148 | } // namespace rocksdb | |
149 | #endif // ROCKSDB_LITE |