Add "nearby" message query.

This commit is contained in:
Paul
2021-07-07 16:21:21 +01:00
parent edd8ef8a1d
commit a4c227ce41
3 changed files with 95 additions and 36 deletions

View File

@@ -1,3 +1,3 @@
#!/bin/bash #!/bin/bash
export version=0.5.1-alpha.5 export version=0.5.1-alpha.6
echo "pub const VERSION: &str = \"${version}\";" > src/version.rs echo "pub const VERSION: &str = \"${version}\";" > src/version.rs

View File

@@ -3,7 +3,7 @@ use std::collections::HashSet;
use crate::database::*; use crate::database::*;
use crate::util::result::{Error, Result}; use crate::util::result::{Error, Result};
use futures::StreamExt; use futures::{StreamExt, try_join};
use mongodb::{ use mongodb::{
bson::{doc, from_document}, bson::{doc, from_document},
options::FindOptions, options::FindOptions,
@@ -28,6 +28,11 @@ pub struct Options {
#[validate(length(min = 26, max = 26))] #[validate(length(min = 26, max = 26))]
after: Option<String>, after: Option<String>,
sort: Option<Sort>, sort: Option<Sort>,
// Specifying 'nearby' ignores 'before', 'after' and 'sort'.
// It will also take half of limit rounded as the limits to each side.
// It also fetches the message ID specified.
#[validate(length(min = 26, max = 26))]
nearby: Option<String>,
include_users: Option<bool>, include_users: Option<bool>,
} }
@@ -48,46 +53,100 @@ pub async fn req(user: User, target: Ref, options: Form<Options>) -> Result<Json
Err(Error::MissingPermission)? Err(Error::MissingPermission)?
} }
let mut query = doc! { "channel": target.id() }; let mut messages = vec![];
if let Some(before) = &options.before { let collection = get_collection("messages");
query.insert("_id", doc! { "$lt": before }); let limit = options.limit.unwrap_or(50);
} let channel = target.id();
if let Some(nearby) = &options.nearby {
if let Some(after) = &options.after { let cursors = try_join!(
query.insert("_id", doc! { "$gt": after }); collection.find(
} doc! {
"channel": channel,
let sort = if let Sort::Latest = options.sort.as_ref().unwrap_or_else(|| &Sort::Latest) { "_id": {
-1 "$gte": &nearby
} else { }
1 },
}; FindOptions::builder()
let mut cursor = get_collection("messages") .limit(limit / 2 + 1)
.find( .sort(doc! {
query, "_id": 1
FindOptions::builder() })
.limit(options.limit.unwrap_or(50)) .build(),
.sort(doc! { ),
"_id": sort collection.find(
}) doc! {
.build(), "channel": channel,
"_id": {
"$lt": &nearby
}
},
FindOptions::builder()
.limit(limit / 2)
.sort(doc! {
"_id": -1
})
.build(),
)
) )
.await
.map_err(|_| Error::DatabaseError { .map_err(|_| Error::DatabaseError {
operation: "find", operation: "find",
with: "messages", with: "messages",
})?; })?;
let mut messages = vec![]; for mut cursor in [ cursors.0, cursors.1 ] {
while let Some(result) = cursor.next().await { while let Some(result) = cursor.next().await {
if let Ok(doc) = result { if let Ok(doc) = result {
messages.push( messages.push(
from_document::<Message>(doc).map_err(|_| Error::DatabaseError { from_document::<Message>(doc).map_err(|_| Error::DatabaseError {
operation: "from_document", operation: "from_document",
with: "message", with: "message",
})?, })?,
); );
}
}
}
} else {
let mut query = doc! { "channel": target.id() };
if let Some(before) = &options.before {
query.insert("_id", doc! { "$lt": before });
}
if let Some(after) = &options.after {
query.insert("_id", doc! { "$gt": after });
}
let sort: i32 = if let Sort::Latest = options.sort.as_ref().unwrap_or_else(|| &Sort::Latest) {
-1
} else {
1
};
let mut cursor = collection
.find(
query,
FindOptions::builder()
.limit(limit)
.sort(doc! {
"_id": sort
})
.build(),
)
.await
.map_err(|_| Error::DatabaseError {
operation: "find",
with: "messages",
})?;
while let Some(result) = cursor.next().await {
if let Ok(doc) = result {
messages.push(
from_document::<Message>(doc).map_err(|_| Error::DatabaseError {
operation: "from_document",
with: "message",
})?,
);
}
} }
} }

View File

@@ -1 +1 @@
pub const VERSION: &str = "0.5.1-alpha.5"; pub const VERSION: &str = "0.5.1-alpha.6";