2015-10-13 14 views

Trả lời

5

Bắt đầu từ phiên bản MongoDB 3.4 chúng tôi có thể e toán tử $indexOfArray để trả về chỉ mục mà tại đó một phần tử đã cho có thể được tìm thấy trong mảng.

$indexOfArray có ba đối số. Đầu tiên là tên của trường mảng có ký hiệu là $.

Thứ hai là phần tử và tùy chọn thứ ba là chỉ mục để bắt đầu tìm kiếm tại. $indexOfArray trả về chỉ mục đầu tiên mà tại đó phần tử được tìm thấy nếu chỉ mục để bắt đầu tìm kiếm tại không được chỉ định.


Demo:

> db.collection.insertOne({ "_id" : 123, "food": [ "apple", "mango", "banana", "mango" ] }) 
{ "acknowledged" : true, "insertedId" : 123 } 
> db.collection.aggregate([ { "$project": { "matchedIndex": { "$indexOfArray": [ "$food", "mango" ] } } } ]) 
{ "_id" : 123, "matchedIndex" : 1 } 
> db.collection.aggregate([ { "$project": { "matchedIndex": { "$indexOfArray": [ "$food", "mango", 2 ] } } } ]) 
{ "_id" : 123, "matchedIndex" : 3 } 
> db.collection.aggregate([ { "$project": { "matchedIndex": { "$indexOfArray": [ "$food", "apricot" ] } } } ] ) 
{ "_id" : 123, "matchedIndex" : -1 } 
+0

Câu trả lời này là tốt nhất cho phiên bản 3.4+, nhưng nếu sử dụng phiên bản cũ, hãy làm theo câu trả lời của @BlakesSeven –

4

Có thực sự là không có cách nào khác ("phía máy chủ") vì sử dụng mapReduce:

db.collection.mapReduce(
    function() { 
     emit(this._id, this.food.indexOf("mango")); 
    }, 
    function() {}, // reducer never gets called since all _id is unique 
    { 
     "out": { "inline": 1 }, 
     "query": { "food": "mango" } 
    } 
) 

Đó là điều duy nhất mà sẽ trở lại một cái gì đó khác trong một hình thức biến đổi khác so với tài liệu riêng của mình , cũng như sử dụng đánh giá JavaScript cần thiết để xác định câu trả lời,

Rất tiếc, không có nhà điều hành "gốc" nào thực hiện việc này. Trừ khi bạn cần điều này cho mục đích tổng hợp thực, thì tốt hơn là chỉ cần thực hiện một "kết hợp chỉ mục mảng" tương tự trong mã gốc trong ứng dụng khách của bạn khi xử lý cơ sở "trên mỗi tài liệu".

+0

làm việc như một nét duyên dáng! Nhưng làm thế nào về hiệu suất trên bộ sưu tập lớn khi gọi mapReduce? –

+0

@ JamesYang Tôi nghĩ rằng bạn cần nắm bắt được điểm mà tôi không nghĩ bạn nên làm điều này, trừ khi bạn thực sự cần phải tổng hợp kết quả hơn nữa (như đã nêu). Không có thay thế phía máy chủ (cũng đã được nêu), do đó bạn bị mắc kẹt với mapReduce trong trường hợp "phía máy chủ" hoặc bạn xử lý chỉ mục mảng cho mỗi tài liệu trong ứng dụng khách (như đã được đề xuất). –

+0

Với tùy chọn '{jsMode: true}', có tốt cho hiệu suất không? trong kinh nghiệm của bạn –

0

Trong vỏ Mongo (trong Robomongo cũng) Tôi sẽ làm như sau:

var food = db.getCollection('yourCollection').findOne({_id: '123'}).food; 
    print('Index of mango: ' + food.indexOf('mango')); 

hoặc bạn có thể lưu mã này trong any_file.js và sau đó chạy từ dòng lệnh:

mongo your_db any_file.js 

Nó sẽ tạo ra một cái gì đó như thế:

MongoDB shell version: 2.4.9 
    connecting to: localhost:27017/your_db 
    Index of mango: 2 
+0

một giải pháp, nhưng có lẽ không thực tế –

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