2012-01-25 36 views
10

Tôi đang tiến hành ước tính MongoDB cho khách hàng của mình. Theo yêu cầu, chúng tôi cần liên kết với một số thực thể ent tập hợp các cặp giá trị tên.Cải thiện các trường truy vấn tồn tại trong MongoDB

db.ent.insert({'a':5775, 'b':'b1'}) 
db.ent.insert({'c':'its a c', 'b':'b2'}) 
db.ent.insert({'a':7557, 'c':'its a c'}) 

Sau này tôi cần phải mạnh mẽ truy vấn ent cho sự hiện diện của các lĩnh vực:

db.ent.find({'a':{$exists:true}}) 
db.ent.find({'c':{$exists:false}}) 

mỗi MongoDB docs:

$ tồn tại không phải là rất hiệu quả ngay cả với một chỉ số, và đặc biệt. với {$ exist: true} vì nó sẽ quét tất cả các giá trị được lập chỉ mục một cách hiệu quả.

các chuyên gia có thể có cung cấp cách hiệu quả hơn (thậm chí với sự thay đổi mô hình) để đối phó nhanh chóng với nhau cặp tên-giá trị

+0

xem: http://www.mongodb.org/display/DOCS/Using+Multikeys+to+Simulate+a+Large+Number+of+ Chỉ mục – Dewfy

Trả lời

9

Bạn có thể thiết kế lại sơ đồ của bạn như thế này:

{ 
    pairs:[ 
    {k: "a", v: 5775}, 
    {k: "b", v: "b1"}, 
    ] 
} 

Sau đó, bạn lập chỉ mục quan trọng của bạn:

db.people.ensureIndex({"pairs.k" : 1}) 

Sau này bạn sẽ có thể tìm kiếm bằng kết hợp chính xác:

db.ent.find({'pairs.k':"a"}) 

Trong trường hợp bạn đi với Chỉ mục thưa thớt và lược đồ hiện tại của bạn, được đề xuất bởi @WesFreeman, bạn sẽ cần tạo chỉ mục trên mỗi khóa bạn muốn tìm kiếm. Nó có thể ảnh hưởng đến hiệu suất ghi hoặc sẽ không thể chấp nhận được nếu các phím của bạn không tĩnh.

+0

Rất thú vị. Nhưng làm thế nào tôi có thể tìm ra tài liệu nào được liên kết với khóa 'a' (sở hữu bởi 'a'). Có cái gì đó giống như '$ cha mẹ ({pairs.k: a})'? – Dewfy

+0

@Dewfy mongodb luôn trả về tài liệu cấp gốc (ngay cả khi bạn tìm kiếm bằng mảng nhúng), vì vậy bạn không cần tìm kiếm cha mẹ, nó sẽ được trả về bởi truy vấn. Chỉ cần thử nó ra và bạn sẽ thấy. –

+0

+1 Thiết kế lại đẹp mắt. Chỉ số thưa thớt có thể nhanh hơn, nếu các phím thực sự thưa thớt, nhưng giống như bạn nói có những hạn chế. –

1

Tôi nghĩ rằng một chỉ số thưa thớt là câu trả lời cho điều này, mặc dù bạn sẽ cần một chỉ mục cho từng trường. http://www.mongodb.org/display/DOCS/Indexes#Indexes-SparseIndexes

Chỉ mục thưa thớt sẽ giúp $ tồn tại: truy vấn đúng.

Thậm chí vẫn còn, nếu trường của bạn không thực sự thưa thớt (có nghĩa là nó chủ yếu được đặt), nó sẽ không giúp bạn nhiều.

Cập nhật Tôi đoán tôi đã sai. Dường như có sự cố mở (https://jira.mongodb.org/browse/SERVER-4187) vẫn tồn tại $ $ không sử dụng chỉ mục thưa thớt. Tuy nhiên, bạn có thể làm một cái gì đó như thế này với tìm và sắp xếp, mà hình như nó đúng cách sử dụng chỉ số thưa thớt:

db.ent.find({}).sort({a:1}); 

Dưới đây là một minh chứng đầy đủ về sự khác biệt, sử dụng giá trị mẫu của bạn:

> db.ent.insert({'a':5775, 'b':'b1'}) 
> db.ent.insert({'c':'its a c', 'b':'b2'}) 
> db.ent.insert({'a':7557, 'c':'its a c'}) 
> db.ent.ensureIndex({a:1},{sparse:true}); 

Lưu ý rằng find({}).sort({a:1}) sử dụng chỉ số (BtreeCursor):

> db.ent.find({}).sort({a:1}).explain(); 
{ 
"cursor" : "BtreeCursor a_1", 
"nscanned" : 2, 
"nscannedObjects" : 2, 
"n" : 2, 
"millis" : 0, 
"nYields" : 0, 
"nChunkSkips" : 0, 
"isMultiKey" : false, 
"indexOnly" : false, 
"indexBounds" : { 
    "a" : [ 
     [ 
      { 
       "$minElement" : 1 
      }, 
      { 
       "$maxElement" : 1 
      } 
     ] 
    ] 
} 
} 

find({a:{$exists:true}}) hiện một đầy đủ quét:

> db.ent.find({a:{$exists:true}}).explain(); 
{ 
"cursor" : "BasicCursor", 
"nscanned" : 3, 
"nscannedObjects" : 3, 
"n" : 2, 
"millis" : 0, 
"nYields" : 0, 
"nChunkSkips" : 0, 
"isMultiKey" : false, 
"indexOnly" : false, 
"indexBounds" : { 

} 
} 

Có vẻ như bạn cũng có thể sử dụng .hint ({a: 1}) để buộc nó sử dụng chỉ mục.

> db.ent.find().hint({a:1}).explain(); 
{ 
"cursor" : "BtreeCursor a_1", 
"nscanned" : 2, 
"nscannedObjects" : 2, 
"n" : 2, 
"millis" : 0, 
"nYields" : 0, 
"nChunkSkips" : 0, 
"isMultiKey" : false, 
"indexOnly" : false, 
"indexBounds" : { 
    "a" : [ 
     [ 
      { 
       "$minElement" : 1 
      }, 
      { 
       "$maxElement" : 1 
      } 
     ] 
    ] 
} 
} 
+0

thực sự 'giải thích' cuối cùng cho thấy vấn đề của tôi - không có chỉ mục được sử dụng để xác định vị trí tài liệu, nhưng nó sẽ được sử dụng mạnh mẽ. Nhưng dù sao, nhờ câu trả lời – Dewfy

+0

Truy vấn đầu tiên của tôi với hàm find() và sort() sử dụng chỉ mục. –

+0

Đã thêm một nhận xét khác về gợi ý(). –

2

Chỉ cần thiết kế lại giản đồ của bạn sao cho đó là truy vấn có thể lập chỉ mục. Trường hợp sử dụng của bạn là tương tự với ứng dụng ví dụ đầu tiên được đưa ra trong MongoDB The Definitive Guide.

Nếu bạn muốn/cần sự tiện lợi của result.a, hãy lưu trữ khóa ở nơi nào đó có thể lập chỉ mục.

thay vì hiện tại:

db.ent.insert({a:5775, b:'b1'}) 

làm

db.ent.insert({a:5775, b:'b1', index: ['a', 'b']}) 

Đó là sau đó một truy vấn lập chỉ mục:

db.end.find({index: "a"}).explain() 
{ 
    "cursor" : "BtreeCursor index_1", 
    "nscanned" : 1, 
    "nscannedObjects" : 1, 
    "n" : 1, 
    "millis" : 0, 
    "nYields" : 0, 
    "nChunkSkips" : 0, 
    "isMultiKey" : true, 
    "indexOnly" : false, 
    "indexBounds" : { 
     "index" : [ 
      [ 
       "a", 
       "a" 
      ] 
     ] 
    } 
} 

hoặc nếu bạn đã từng có khả năng truy vấn còn bởi giá trị:

db.ent.insert({ 
    a:5775, 
    b:'b1', 
    index: [ 
     {name: 'a', value: 5775}, 
     {name: 'b', value: 'b1'} 
    ] 
}) 

Đó cũng là một truy vấn lập chỉ mục:

db.end.find({"index.name": "a"}).explain() 
{ 
    "cursor" : "BtreeCursor index.name_", 
    "nscanned" : 1, 
    "nscannedObjects" : 1, 
    "n" : 1, 
    "millis" : 0, 
    "nYields" : 0, 
    "nChunkSkips" : 0, 
    "isMultiKey" : true, 
    "indexOnly" : false, 
    "indexBounds" : { 
     "index.name" : [ 
      [ 
       "a", 
       "a" 
      ] 
     ] 
    } 
} 
+0

cách đẹp (+1), nhưng trông hơi dư thừa – Dewfy

0

Làm thế nào về việc thiết lập không tồn tại hiện trường để null? Sau đó, bạn có thể truy vấn chúng với {field: {$ne: null}}.

db.ent.insert({'a':5775, 'b':'b1', 'c': null}) 
db.ent.insert({'a': null, 'b':'b2', 'c':'its a c'}) 
db.ent.insert({'a':7557, 'b': null, 'c':'its a c'}) 

db.ent.ensureIndex({"a" : 1}) 
db.ent.ensureIndex({"b" : 1}) 
db.ent.ensureIndex({"c" : 1}) 

db.ent.find({'a':{$ne: null}}).explain() 

Dưới đây là kết quả:

{ 
    "cursor" : "BtreeCursor a_1 multi", 
    "isMultiKey" : false, 
    "n" : 4, 
    "nscannedObjects" : 4, 
    "nscanned" : 5, 
    "nscannedObjectsAllPlans" : 4, 
    "nscannedAllPlans" : 5, 
    "scanAndOrder" : false, 
    "indexOnly" : false, 
    "nYields" : 0, 
    "nChunkSkips" : 0, 
    "millis" : 0, 
    "indexBounds" : { 
     "a" : [ 
      [ 
       { 
        "$minElement" : 1 
       }, 
       null 
      ], 
      [ 
       null, 
       { 
        "$maxElement" : 1 
       } 
      ] 
     ] 
    }, 
    "server" : "my-laptop" 
} 
+1

truy vấn "$ ne" không thể sử dụng chỉ mục. http://docs.mongodb.org/manual/faq/indexes/#using-ne-and-nin-in-a-query-is-slow-why – Megawolt

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