Query using metadata #391
-
Is your feature request related to a problem? Please describe.I'm currently trying to query stripe service but I don't have the customer ID and would like to avoid querying the entire list then filtering in code. Is there currently a way to do this that I'm missing or is it not available yet? Describe the solution you'd likeIn the Javascript SDK I can use something like this: await this.stripeClient.customers
.search({ query: `metadata["memberId"]:"${memberId}"` }) So I was hoping there would be an equivalent in Rust, maybe like: let mut customer_params = ListCustomers::new();
customer_params.expand = &vec!["metadata[\"member_id\"]"];
customer_params.query = format!("metadata[\"member_id\"]:{member_id}");
let customers = Customer::list(&self.client, &customer_params).await?; Describe alternatives you've consideredThe alternative is to filter after I query the entire list using an expanded metadata object. Additional contextNo response |
Beta Was this translation helpful? Give feedback.
Replies: 6 comments 1 reply
-
Currently my code looks like what I've pasted below because I need to query for a metadata field called async fn get_subscriptions(&self, member_id: &Uuid) -> Result<Vec<Subscription>> {
let customers = Customer::list(
&self.client,
&ListCustomers {
expand: &vec!["metadata"],
..ListCustomers::default()
},
)
.await?;
let customer_ids = customers
.data
.into_iter()
.filter_map(|customer| {
let m_id = match customer.metadata.get("member_id") {
Some(m_id) => m_id,
_ => return None,
};
if m_id == &member_id.to_string() {
Some(customer.id.clone());
}
None
})
.collect::<Vec<CustomerId>>();
let futures = FuturesUnordered::new();
for id in customer_ids {
futures.push(Subscription::list(&self.client, &ListSubscriptions {
customer: Some(id),
..ListSubscriptions::default()
}))
}
let subscriptions: Vec<Subscription> = join_all(futures)
.await
.into_iter()
.filter_map(|x| match x {
Ok(sub_list) => Some(sub_list),
_ => None,
})
.map(|sub_list| sub_list.data)
.flatten()
.collect();
Ok(subscriptions)
} |
Beta Was this translation helpful? Give feedback.
-
Need this!! Searching by metadata is really important |
Beta Was this translation helpful? Give feedback.
-
Workaround: #[derive(Serialize, Default, Debug)]
pub(crate) struct SearchParams {
pub query: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub limit: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub page: Option<u64>,
}
pub(crate) async fn stripe_search<R: DeserializeOwned + 'static + Send>(
client: &stripe::Client,
resource: &str,
params: SearchParams,
) -> Result<List<R>, stripe::StripeError> {
client
.get_query(&format!("/{}/search", resource), ¶ms)
.await
} |
Beta Was this translation helpful? Give feedback.
-
I ended up not using Rust as this was a POC and the company decided to use JS (unrelated to this issue). But seeing this brought up again made me think. Perhaps this feature isn't possible or not likely to be on the roadmap... If I were to implement this again I'd probably just end up storing the customer ID internally or in whatever system needs to access the subscriptions. Seems like the most efficient solution without writing custom application layer workarounds IMO but I suppose each scenario is unique. 😄 |
Beta Was this translation helpful? Give feedback.
-
@onx2 I also realized it was not an option for me because I learnt that the meta data is not instantly queryable. It can take up to a minute for the search index to update My code was creating multiple customers instead of one so I had to resort to storing the customer ID internally. However the code above does work for any resource, but note that search results are not safe for read-after-write operations |
Beta Was this translation helpful? Give feedback.
-
I am going to move this to discussions, thanks for opening! :) |
Beta Was this translation helpful? Give feedback.
Workaround: