2012-02-21 65 views
13

Tôi hiện đang viết một phương pháp tìm kiếm cho các ứng dụng đường ray của tôi, và tại thời điểm nó hoạt động tốt. Tôi đã điều sau đây trong game.rb tôi:Tìm kiếm nhiều cột - Rails

def self.search(search) 
    if search 
    find(:all, :conditions => ['game_name LIKE ? OR genre LIKE ? OR console LIKE ?', "%#{search}%", "#{search}", "#{search}"]) 
    else 
    find(:all) 
    end 
end 

Bây giờ để tìm kiếm tốt, nhưng vấn đề của tôi là nếu có một kỷ lục trong GAME_NAME có từ 'playstation' trong nó, nó sẽ kết thúc việc tìm kiếm có . Nó chỉ trả về bản ghi đó, thay vì tất cả các trò chơi có 'playstation' được lưu trữ trong bảng điều khiển. Bây giờ tôi hiểu điều này là bởi vì tôi có 'HOẶC' trong điều kiện của tôi, nhưng tôi không biết thay thế. 'AND' yêu cầu tất cả các điều kiện để khớp hoặc không trả lại gì cả. Tôi có thể sử dụng phương án thay thế nào cho AND và OR? Trợ giúp sẽ được nhiều đánh giá cao.

Nếu có giải pháp có các hộp và mục nhập tìm kiếm riêng biệt, thì điều đó sẽ ổn, tôi không nhất thiết yêu cầu tìm kiếm tất cả dựa trên một biểu mẫu tìm kiếm.

+0

Có thể là một giải pháp cho bạn là sử dụng một viên ngọc cho những gì bạn muốn như https://github.com/ernie/meta_where – Awea

Trả lời

25

Nếu tôi hiểu câu hỏi của bạn một cách chính xác, SQL của bạn có vẻ tốt với tôi đối với những gì bạn đang cố gắng làm. Một mệnh đề OR sẽ trả về tất cả các bản ghi khớp với cột1, cột2 hoặc cột3. Nó không dừng lại ở trận đấu đầu tiên. Tôi thấy một vấn đề với các thông số của bạn trong đó đầu tiên bạn đang sử dụng LIKE với% nhưng trong hai thứ hai bạn không, có lẽ đó là nơi mà vấn đề của bạn đến từ.

Đây có phải là tìm kiếm của bạn (% xung quanh tìm kiếm thứ hai và thứ ba) không?

find(:all, :conditions => ['game_name LIKE ? OR genre LIKE ? OR console LIKE ?', "%#{search}%", "%#{search}%", "%#{search}%"]) 

hoặc tốt hơn sử dụng phiên bản DRY (trên sẽ không làm việc cho Rails 4.2 trở lên):

Item.where('game_name LIKE :search OR genre LIKE :search OR console LIKE :search', search: "%#{search}%") 
+1

Thanks a lot Jeff, tôi đặt% xung quanh tìm kiếm thứ hai và thứ ba và nó làm việc tốt, thậm chí không nhận thấy rằng thiếu. Chúc mừng cho tất cả sự giúp đỡ. – user1222136

+1

@items = Item.where ('game_name LIKE: tìm kiếm HOẶC thể loại LIKE: tìm kiếm HOẶC giao diện điều khiển LIKE: tìm kiếm', tìm kiếm: "% # {search}%"). Order (: name) – sunil

16

gì nếu bạn có 15 cột để tìm kiếm thì bạn sẽ lặp lại chính 15 lần. Thay vì lặp lại khóa 15 lần trong truy vấn, bạn có thể viết như sau:

key = "%#{search}%" 

@items = Item.where('game_name LIKE :search OR genre LIKE :search OR console LIKE :search', search: key).order(:name) 

Nó sẽ cho bạn kết quả tương tự.

Cảm ơn

4

Tôi nghĩ đây là một giải pháp gọn gàng hơn. Điều này cho phép bạn thêm/xóa cột dễ dàng hơn.

key = "%#{search}%" 
columns = %w{game_name genre console} 
@items = Item.where(
    columns 
    .map {|c| "#{c} like :search" } 
    .join(' OR '), 
    search: key 
) 
+0

Câu trả lời giống nhau nhưng điều này chắc chắn là lần đọc tốt hơn. Hiệu suất sẽ có một hit mặc dù, phải không? Trong tất cả các câu trả lời, nó so sánh một khóa với nhiều cột, bạn càng cần phải xem nhiều cột hơn. Có cách nào tốt hơn không? – Breno

+0

@ Breno - Cách duy nhất tôi có thể nghĩ là ghép nối tất cả các trường và sau đó tìm kiếm trường mới. fields =: name,: address_1,: address_2 Item.where ("concat_ws ('', # {fields.join (',')}) LIKE?", "% # {Key}%") –

Các vấn đề liên quan