2016-08-05 14 views
1

私は単純な検索機能を構築しており、文字列フィールド内に文字列を持つすべてのレコードを検索したいと考えています。文字列フィールドに他の文字列が含まれているEctoクエリ

これは私が試みたことです。

  • Sandichモービーが
  • マイMobyand例
  • リーン

    • 白鯨しかし、私は得る::

      term = "Moby" 
      MyApp.Book 
      |> where([p], String.contains?(p, term)) 
      |> order_by(desc: :inserted_at) 
      

      これは、次の本を返します

      `String.contains?(p, term)` is not a valid query expression 
      
      ここ

    答えて

    3

    あなたが(それは、エンドユーザーが入力したなら)入力に%をエスケープするString.replace/3を使用して、クエリ内likeを使用する必要があります:

    |> where([p], like(p.title, ^"%#{String.replace(term, "%", "\\%")}%")) 
    

    例:

    iex(1)> term = "Foo%Bar" 
    iex(2)> query = MyApp.Post |> where([p], like(p.title, ^"%#{String.replace(term, "%", "\\%")}%")) |> order_by(desc: :inserted_at) 
    #Ecto.Query<from p in MyApp.Post, where: like(p.title, ^"%Foo\\%Bar%"), 
    order_by: [desc: p.inserted_at]> 
    iex(3)> Ecto.Adapters.SQL.to_sql(:all, MyApp.Repo, query) 
    {"SELECT p0.\"id\", p0.\"title\", p0.\"user_id\", p0.\"inserted_at\", p0.\"updated_at\" FROM \"posts\" AS p0 WHERE (p0.\"title\" LIKE $1) ORDER BY p0.\"inserted_at\" DESC", 
    ["%Foo\\%Bar%"]} 
    

    あなたは、のような用語を交換をしない場合%をエスケープする必要があるか、0以上の任意の文字列に一致するため、は"azb"と一致します。

    +0

    ドッグベット・ユー・ロック。私はStackOverflowでユーザーに従うことができたらいいと思う。エリクサーグッズのお宝をお届けします。 :いいぞ: –

    1

    は、あなたがそれを行う方法は次のとおりです。

    results = 
        from b in Book, 
        where: ilike(t.name, ^"%#{params["term"]}%"), 
        order_by: [desc: :inserted_at] 
    
    +0

    あなたはSQLインジェクション攻撃にこんにちはと言っています。 MattWのやり方でやってください。 – JustMichael

    +0

    @JustMichael彼は与えられた言葉の前後に '%'を追加する必要があります。 – coderVishal

    +0

    @JustMichaelここにはSQLインジェクションはありませんが、 'params [" term "]'に '%'が含まれていれば、0以上の文字列にマッチするものとして扱われます。また、MattWの現在のコードは動作しません。 – Dogbert

    関連する問題