Kiểm tra nếu một trường có chứa một chuỗi


454

Tôi đang tìm kiếm một toán tử, cho phép tôi kiểm tra, nếu giá trị của một trường có chứa một chuỗi nhất định.

Cái gì đó như:

db.users.findOne({$contains:{"username":"son"}})

Điều đó có thể không?

Câu trả lời:


693

Bạn có thể làm điều đó với mã sau đây.

db.users.findOne({"username" : {$regex : ".*son.*"}});

16
Lưu ý rằng điều này sẽ không sử dụng hiệu quả một chỉ mục và dẫn đến tất cả các giá trị được quét cho phù hợp. Xem ghi chú về Biểu thức chính quy
Stennie

7
@Stennie, vậy thì bạn đề nghị gì để sử dụng chỉ mục hiệu quả và tìm một chuỗi con.
Bầu trời xanh

4
@Vish: nếu trường hợp sử dụng phổ biến của bạn là tìm kiếm văn bản tự do của một trường và bạn có số lượng lớn tài liệu, tôi sẽ mã hóa văn bản cho các truy vấn hiệu quả hơn. Bạn có thể sử dụng multikeys cho tìm kiếm toàn văn bản đơn giản hoặc có thể xây dựng một chỉ mục đảo ngược như một bộ sưu tập riêng biệt. Đối với các tìm kiếm không thường xuyên hoặc một bộ sưu tập nhỏ các tài liệu, việc quét toàn bộ chỉ mục có thể được chấp nhận (mặc dù không tối ưu).
Stennie

98
Đây không phải là một chút quá mức? Những gì bạn muốn là db.users.findOne({"username" : {$regex : "son"}});
JamieJag

3
Có thể muốn kiểm tra tìm kiếm toàn văn bản trong Mongo 2.6
wprl

179

Vì vỏ Mongo hỗ trợ regex, điều đó hoàn toàn có thể.

db.users.findOne({"username" : /.*son.*/});

Nếu chúng tôi muốn truy vấn không phân biệt chữ hoa chữ thường, chúng tôi có thể sử dụng tùy chọn "i", như hiển thị bên dưới:

db.users.findOne({"username" : /.*son.*/i});

Xem: http://www.mongodb.org/display/DOCS/Advified+Queries#AdvifiedQueries-RegularExpressions


1
Vui lòng bao gồm một đoạn mã thể hiện việc sử dụng các biểu thức thông thường để tìm kiếm. Câu trả lời nên bao gồm nhiều thông tin hơn chỉ là một liên kết ...
maerics

1
Câu trả lời được chọn không phù hợp với tôi, nhưng câu trả lời này đã làm (Tôi đang thực hiện các truy vấn mongo thông qua các lệnh thực thi docker) Tôi nghĩ rằng câu trả lời này nên là câu trả lời được chọn vì nó có vẻ linh hoạt hơn.
Arthur Weborg

5
giống như các bình luận trong câu trả lời được chọn, tôi tin rằng db.users.findOne({"username" : /.*son.*/});cũng có thể là quá mức cần thiết và regex có thể đơn giản là/son/
Arthur Weborg

2
Cách ngắn gọn hơn là sử dụng $ regex
Lionet Chen

4
Chỉnh sửa phần này để chỉ sử dụng{ username: /son/ }
Wyck

150

https://docs.mongodb.com/manual/reference/sql-comparison/

http://php.net/manual/en/mongo.sqltomongo.php

MySQL

SELECT * FROM users WHERE username LIKE "%Son%"

MongoDB

db.users.find({username:/Son/})

8
Câu trả lời MongoDB của bạn là tốt; xem xét chỉnh sửa câu hỏi của bạn để loại bỏ lời khuyên MySQL không liên quan.
maerics

31
Xóa tất cả các truy vấn hoặc thay đổi nó? SQL được biết đến nhiều nhất, nó rất hữu ích để hiểu MongoDB
Zheng Kai

4
@ZhengKai: trên trang web này, bạn thường nên trả lời trực tiếp câu hỏi, chỉ sử dụng các công nghệ cụ thể được gắn thẻ và yêu cầu.
maerics

98
@maerics cá nhân Tôi thấy việc đưa vào MySQL của Trịnh rất hữu ích vì nó cung cấp một điểm tinh chỉnh.
Mike Bartlett

50
Tôi cũng tìm thấy tài liệu tham khảo SQL có liên quan, tôi nghĩ nó nên ở lại.
vikingsteve 11/11/13

69

Kể từ phiên bản 2.4, bạn có thể tạo một chỉ mục văn bản trên (các) trường để tìm kiếm và sử dụng toán tử $ text để truy vấn.

Đầu tiên, tạo chỉ mục:

db.users.createIndex( { "username": "text" } )

Sau đó, để tìm kiếm:

db.users.find( { $text: { $search: "son" } } )

Điểm chuẩn (~ 150K tài liệu):

  • Regex (câu trả lời khác) => 5,6-6,9 giây
  • Tìm kiếm văn bản => .164-.201 giây

Ghi chú:

  • Một bộ sưu tập có thể chỉ có một chỉ mục văn bản. Bạn có thể sử dụng chỉ mục văn bản ký tự đại diện nếu bạn muốn tìm kiếm bất kỳ trường chuỗi nào , như thế này : db.collection.createIndex( { "$**": "text" } ).
  • Một chỉ mục văn bản có thể lớn. Nó chứa một mục nhập chỉ mục cho mỗi từ xuất phát sau duy nhất trong mỗi trường được lập chỉ mục cho mỗi tài liệu được chèn.
  • Một chỉ mục văn bản sẽ mất nhiều thời gian để xây dựng hơn một chỉ mục bình thường.
  • Một chỉ mục văn bản không lưu trữ các cụm từ hoặc thông tin về sự gần gũi của các từ trong tài liệu. Do đó, các truy vấn cụm từ sẽ chạy hiệu quả hơn nhiều khi toàn bộ bộ sưu tập vừa với RAM.

14
không, toán tử văn bản nguyên vẹn không cho phép thực thi "chứa", do đó, nó sẽ chỉ trả về kết hợp từ chính xác, tùy chọn duy nhất hiện tại là 3.0 là sử dụng regex, tức là db.users.find ({tên người dùng: / son / i} ) cái này sẽ tra cứu mọi người dùng có chứa "son" (case-
insenstive

3
Bạn có phải reindex khi bạn thêm hoặc xóa tài liệu vào / ra khỏi bộ sưu tập không?
Jake Wilson

Tiêu đề của câu hỏi "chứa". tìm kiếm toàn văn không được áp dụng cho câu hỏi.
Donato

29

Vì đây là một trong những lần truy cập đầu tiên trong các công cụ tìm kiếm và dường như không có cách nào ở trên hoạt động cho MongoDB 3.x, đây là một tìm kiếm regex hoạt động:

db.users.find( { 'name' : { '$regex' : yourvalue, '$options' : 'i' } } )

Không cần phải tạo và thêm chỉ mục hoặc như nhau.


1
Regexes cần được vệ sinh.
sean

16

Đây là những gì bạn phải làm nếu bạn đang kết nối MongoDB thông qua Python

db.users.find({"username": {'$regex' : '.*' + 'Son' + '.*'}})

bạn cũng có thể sử dụng tên biến thay vì 'Son' và do đó nối chuỗi.


trong es2015, bạn có thể sử dụng backticks {$ regex: .*${value}.*}
Michael Guild

16

Cách đơn giản nhất để hoàn thành nhiệm vụ này

Nếu bạn muốn truy vấn phân biệt chữ hoa chữ thường

db.getCollection("users").find({'username':/Son/})

Nếu bạn muốn truy vấn không phân biệt chữ hoa chữ thường

db.getCollection("users").find({'username':/Son/i})

1
Làm thế nào để sử dụng biến với regex ??
Hisham

4

câu trả lời lý tưởng chỉ số sử dụng i của nó cho trường hợp không nhạy cảm

db.users.findOne({"username" : new RegExp(search_value, 'i') });

Regexes cần được vệ sinh.
sean


1

Cách bỏ qua các thẻ HTML trong trận đấu RegExp:

var text = '<p>The <b>tiger</b> (<i>Panthera tigris</i>) is the largest <a href="https://stackoverflow.com/wiki/Felidae" title="Felidae">cat</a> <a href="https://stackoverflow.com/wiki/Species" title="Species">species</a>, most recognizable for its pattern of dark vertical stripes on reddish-orange fur with a lighter underside. The species is classified in the genus <i><a href="https://stackoverflow.com/wiki/Panthera" title="Panthera">Panthera</a></i> with the <a href="https://stackoverflow.com/wiki/Lion" title="Lion">lion</a>, <a href="https://stackoverflow.com/wiki/Leopard" title="Leopard">leopard</a>, <a href="https://stackoverflow.com/wiki/Jaguar" title="Jaguar">jaguar</a>, and <a href="https://stackoverflow.com/wiki/Snow_leopard" title="Snow leopard">snow leopard</a>. It is an <a href="https://stackoverflow.com/wiki/Apex_predator" title="Apex predator">apex predator</a>, primarily preying on <a href="https://stackoverflow.com/wiki/Ungulate" title="Ungulate">ungulates</a> such as <a href="https://stackoverflow.com/wiki/Deer" title="Deer">deer</a> and <a href="https://stackoverflow.com/wiki/Bovid" class="mw-redirect" title="Bovid">bovids</a>.</p>';
var searchString = 'largest cat species';

var rx = '';
searchString.split(' ').forEach(e => {
  rx += '('+e+')((?:\\s*(?:<\/?\\w[^<>]*>)?\\s*)*)';
});

rx = new RegExp(rx, 'igm');

console.log(text.match(rx));

Điều này có lẽ rất dễ dàng để biến thành bộ lọc tổng hợp MongoDB.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.