-
-
Notifications
You must be signed in to change notification settings - Fork 37
/
view-examples.rs
115 lines (99 loc) · 3.84 KB
/
view-examples.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
use bonsaidb::core::document::{CollectionDocument, Emit};
use bonsaidb::core::schema::{
Collection, CollectionMapReduce, ReduceResult, SerializedCollection, SerializedView, View,
ViewMapResult, ViewMappedValue, ViewSchema,
};
use bonsaidb::local::config::{Builder, StorageConfiguration};
use bonsaidb::local::Database;
use serde::{Deserialize, Serialize};
// begin rustme snippet: snippet-a
#[derive(Debug, Serialize, Deserialize, Collection)]
#[collection(name = "shapes", views = [ShapesByNumberOfSides])]
struct Shape {
pub sides: u32,
}
#[derive(Debug, Clone, View, ViewSchema)]
#[view(collection = Shape, key = u32, value = usize, name = "by-number-of-sides")]
struct ShapesByNumberOfSides;
impl CollectionMapReduce for ShapesByNumberOfSides {
fn map<'doc>(&self, document: CollectionDocument<Shape>) -> ViewMapResult<'doc, Self::View> {
document
.header
.emit_key_and_value(document.contents.sides, 1)
}
fn reduce(
&self,
mappings: &[ViewMappedValue<'_, Self>],
_rereduce: bool,
) -> ReduceResult<Self::View> {
Ok(mappings.iter().map(|m| m.value).sum())
}
}
// end rustme snippet
fn main() -> Result<(), bonsaidb::core::Error> {
// begin rustme snippet: snippet-b
let db = Database::open::<Shape>(StorageConfiguration::new("view-examples.bonsaidb"))?;
// Insert a new document into the Shape collection.
Shape { sides: 3 }.push_into(&db)?;
// end rustme snippet
// Views in BonsaiDb are written using a Map/Reduce approach. In this
// example, we take a look at how document mapping can be used to filter and
// retrieve data
//
// Let's start by seeding the database with some shapes of various sizes:
for sides in 3..=20 {
Shape { sides }.push_into(&db)?;
}
// And, let's add a few shapes with the same number of sides
Shape { sides: 3 }.push_into(&db)?;
Shape { sides: 4 }.push_into(&db)?;
// At this point, our database should have 3 triangles:
// begin rustme snippet: snippet-c
let triangles = ShapesByNumberOfSides::entries(&db).with_key(&3).query()?;
println!("Number of triangles: {}", triangles.len());
// end rustme snippet
// What is returned is a list of entries containing the document id
// (source), the key of the entry, and the value of the entry:
println!("Triangles: {triangles:#?}");
// If you want the associated documents, use query_with_collection_docs:
for entry in &ShapesByNumberOfSides::entries(&db)
.with_key(&3)
.query_with_collection_docs()?
{
println!(
"Shape ID {} has {} sides",
entry.document.header.id, entry.document.contents.sides
);
}
// The reduce() function takes the "values" emitted during the map()
// function, and reduces a list down to a single value. In this example, the
// reduce function is acting as a count. So, if you want to query for the
// number of shapes, we don't need to fetch all the records, we can just
// retrieve the result of the calculation directly.
//
// So, here we're using reduce() to count the number of shapes with 4 sides.
println!(
"Number of quads: {} (expected 2)",
ShapesByNumberOfSides::entries(&db).with_key(&4).reduce()?
);
// Or, 5 shapes that are triangles or quads
println!(
"Number of quads and triangles: {} (expected 5)",
ShapesByNumberOfSides::entries(&db)
.with_keys(&[3, 4])
.reduce()?
);
// And, 10 shapes that have more than 10 sides
println!(
"Number of shapes with more than 10 sides: {} (expected 10)",
ShapesByNumberOfSides::entries(&db)
.with_key_range(11..)
.reduce()?
);
Ok(())
}
#[test]
fn runs() {
drop(std::fs::remove_dir_all("view-examples.bonsaidb"));
main().unwrap()
}