1
1
use bonsaidb::{
2
    core::{
3
        connection::Connection,
4
        document::{BorrowedDocument, Emit},
5
        schema::{
6
            view::map::ViewMappedValue, Collection, ReduceResult, SerializedCollection, View,
7
            ViewMapResult, ViewSchema,
8
        },
9
        Error,
10
    },
11
    local::{
12
        config::{Builder, StorageConfiguration},
13
        Database,
14
    },
15
};
16
use serde::{Deserialize, Serialize};
17

            
18
// ANCHOR: struct
19
49
#[derive(Serialize, Deserialize, Debug, Collection)]
20
#[collection(name = "blog-post", views = [BlogPostsByCategory])]
21
pub struct BlogPost {
22
    pub title: String,
23
    pub body: String,
24
    pub category: Option<String>,
25
}
26
// ANCHOR_END: struct
27

            
28
// ANCHOR: view
29
32
#[derive(Debug, Clone, View)]
30
#[view(collection = BlogPost, key = Option<String>, value = u32, name = "by-category")]
31
pub struct BlogPostsByCategory;
32

            
33
impl ViewSchema for BlogPostsByCategory {
34
    type View = Self;
35

            
36
3
    fn map(&self, document: &BorrowedDocument<'_>) -> ViewMapResult<Self::View> {
37
3
        let post = BlogPost::document_contents(document)?;
38
3
        document.header.emit_key_and_value(post.category, 1)
39
3
    }
40

            
41
3
    fn reduce(
42
3
        &self,
43
3
        mappings: &[ViewMappedValue<Self::View>],
44
3
        _rereduce: bool,
45
3
    ) -> ReduceResult<Self::View> {
46
5
        Ok(mappings.iter().map(|mapping| mapping.value).sum())
47
3
    }
48
}
49
// ANCHOR_END: view
50

            
51
#[allow(unused_variables)]
52
1
#[test]
53
1
fn example() -> Result<(), Error> {
54
1
    drop(std::fs::remove_dir_all("example.bonsaidb"));
55
1
    let db = Database::open::<BlogPost>(StorageConfiguration::new("example.bonsaidb"))?;
56
    // ANCHOR: insert_data
57
1
    BlogPost {
58
1
        title: String::from("New version of BonsaiDb released"),
59
1
        body: String::from("..."),
60
1
        category: Some(String::from("Rust")),
61
1
    }
62
1
    .push_into(&db)?;
63

            
64
1
    BlogPost {
65
1
        title: String::from("New Rust version released"),
66
1
        body: String::from("..."),
67
1
        category: Some(String::from("Rust")),
68
1
    }
69
1
    .push_into(&db)?;
70

            
71
1
    BlogPost {
72
1
        title: String::from("Check out this great cinnamon roll recipe"),
73
1
        body: String::from("..."),
74
1
        category: Some(String::from("Cooking")),
75
1
    }
76
1
    .push_into(&db)?;
77
    // ANCHOR_END: insert_data
78
    // ANCHOR: query_with_docs
79
1
    let rust_posts = db
80
1
        .view::<BlogPostsByCategory>()
81
1
        .with_key(Some("Rust"))
82
1
        .query_with_docs()?;
83
3
    for mapping in &rust_posts {
84
2
        let post = BlogPost::document_contents(mapping.document)?;
85
2
        println!(
86
2
            "Retrieved post #{} \"{}\"",
87
2
            mapping.document.header.id, post.title
88
2
        );
89
    }
90
    // ANCHOR_END: query_with_docs
91
1
    assert_eq!(rust_posts.len(), 2);
92
    // ANCHOR: query_with_collection_docs
93
1
    let rust_posts = db
94
1
        .view::<BlogPostsByCategory>()
95
1
        .with_key(Some("Rust"))
96
1
        .query_with_collection_docs()?;
97
3
    for mapping in &rust_posts {
98
2
        println!(
99
2
            "Retrieved post #{} \"{}\"",
100
2
            mapping.document.header.id, mapping.document.contents.title
101
2
        );
102
2
    }
103
    // ANCHOR_END: query_with_collection_docs
104
1
    assert_eq!(rust_posts.len(), 2);
105
    // ANCHOR: reduce_one_key
106
1
    let rust_post_count = db
107
1
        .view::<BlogPostsByCategory>()
108
1
        .with_key(Some("Rust"))
109
1
        .reduce()?;
110
1
    assert_eq!(rust_post_count, 2);
111
    // ANCHOR_END: reduce_one_key
112
    // ANCHOR: reduce_multiple_keys
113
1
    let total_post_count = db.view::<BlogPostsByCategory>().reduce()?;
114
1
    assert_eq!(total_post_count, 3);
115
    // ANCHOR_END: reduce_multiple_keys
116
1
    Ok(())
117
1
}