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
26
#[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
#[tokio::test]
53
1
async fn example() -> Result<(), Error> {
54
1
    drop(tokio::fs::remove_dir_all("example.bonsaidb").await);
55
18
    let db = Database::open::<BlogPost>(StorageConfiguration::new("example.bonsaidb")).await?;
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
1
    .await?;
64

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

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