Search code examples
postgresqlrustrust-diesel

How to do a IN query using diesel?


I want to do an IN query with diesel using PostgreSQL 13 to select songs collection from songs table in some id collections. The SQL executed by the database may look like this:

select * from songs where id in(1,2,3)

what I tried to do using rust diesel way like this:

pub fn songs(ids: Vec<i64>){
    use schema::songs::dsl::*;
    let connection = config::establish_connection();
    let results = songs.filter(id.contains(ids))
        .load::<QuerySongs>(&connection)
        .expect("Error loading posts");
}

seems did not work, when I compile the project code using cargo build shows error like this:

error[E0599]: the method `contains` exists for struct `songs::schema::songs::columns::id`, but its trait bounds were not satisfied
  --> src/biz/music/songs.rs:37:35
   |
37 |       let results = songs.filter(id.contains(ids))
   |                                     ^^^^^^^^ method cannot be called on `songs::schema::songs::columns::id` due to unsatisfied trait bounds

I read the docs and source code demo but it was so short and did not mention about how to execute a query by id in a collection. What should I do to make a IN query in rust diesel(diesel = { version = "1.4.4", features = ["postgres"] })? Here is a minimal reproducible demo.


Solution

  • You're looking for .eq_any():

    Creates a SQL IN statement.

    let results = songs.filter(id.eq_any(ids))
        .load::<QuerySongs>(&connection)
        .expect("Error loading posts");
    

    If using Diesel 2.x with PostgreSQL, this will automatically be converted into a = ANY() query (docs):

    Queries using this method will not typically be placed in the prepared statement cache. However, in cases when a subquery is passed to the method, that query will use the cache (assuming the subquery itself is safe to cache). On PostgreSQL, this method automatically performs a = ANY() query.

    If using Diesel 1.x with PostgreSQL, you should use eq(any(...)) instead (docs).

    Queries using this method will not be placed in the prepared statement cache. On PostgreSQL, you should use eq(any()) instead. This method may change in the future to automatically perform = ANY on PostgreSQL.

    A little self-fulfilling prophecy there.