2016-06-09 13 views
5

Về cơ bản, tiêu đề cho biết.Tìm tài liệu có trường mảng chứa ít nhất n phần tử của một mảng nhất định

Input: myArray = một mảng các từ

Tôi có một mô hình mà có lĩnh vực wordsCollection, đó là một lĩnh vực mảng.

Làm thế nào tôi có thể tìm thấy tất cả các văn bản của mô hình đó mà wordsCollections có ít nhất n phần tử của myArray

+0

cấu trúc Hiện db và những gì yo đã cố gắng cho đến nay để làm cho nó làm việc. – Shrabanee

+0

Tôi không nghĩ rằng câu hỏi là đủ rõ ràng rằng tôi không cần phải cung cấp cấu trúc db. Tôi không chắc liệu mongodb cung cấp một cuộc gọi API như vậy, vì vậy tôi chỉ nghĩ về việc lặp qua tất cả các tài liệu .... Tất nhiên, nó có vẻ thực sự xấu –

+0

Các mục của 'myArray' và' wordsCollection' có độc đáo không? – Redu

Trả lời

3

Hãy nói chúng tôi có các tài liệu sau trong bộ sưu tập của chúng tôi:

{ "_id" : ObjectId("5759658e654456bf4a014d01"), "a" : [ 1, 3, 9, 2, 9, 0 ] } 
{ "_id" : ObjectId("5759658e654456bf4a014d02"), "a" : [ 0, 8, 1 ] } 
{ "_id" : ObjectId("5759658e654456bf4a014d03"), "a" : [ 0, 8, 432, 9, 34, -3 ] } 
{ "_id" : ObjectId("5759658e654456bf4a014d04"), "a" : [ 0, 0, 4, 3, 2, 7 ] } 

và mảng đầu vào sau và n = 2

var inputArray = [1, 3, 0]; 

Chúng tôi có thể trả lại các tài liệu đó trong đó trường mảng chứa ít nhất n phần tử của một cho mảng sử dụng khung tổng hợp.

$match chỉ chọn những tài liệu có độ dài của mảng lớn hơn hoặc bằng n. Điều này làm giảm lượng dữ liệu được xử lý xuống trong đường ống.

Các nhà điều hành đường ống $redact sử dụng một chế biến điều kiện logic bằng cách sử dụng $cond điều hành và các hoạt động đặc biệt $$KEEP để "giữ" các tài liệu nơi điều kiện logic là đúng hay $$PRUNE để "loại bỏ" các tài liệu nơi điều kiện là sai.

Trong trường hợp của chúng tôi, tình trạng này là $gte mà trả về true nếu $size của giao nhau của hai mảng, mà chúng tôi tính toán sử dụng toán tử $setIntersection là lớn hơn hoặc bằng 2.

db.collection.aggregate(
    [ 
     { "$match": { "a.1": { "$exists": true } } }, 
     { "$redact": { 
      "$cond": [ 
       { "$gte": [ 
        { "$size": { "$setIntersection": [ "$a", inputArray ] } }, 
        2 
       ]}, 
       "$$KEEP", 
       "$$PRUNE" 
      ] 
     }} 
    ] 
) 

trong đó sản xuất:

{ "_id" : ObjectId("5759658e654456bf4a014d01"), "a" : [ 1, 3, 9, 2, 9, 0 ] } 
{ "_id" : ObjectId("5759658e654456bf4a014d02"), "a" : [ 0, 8, 1 ] } 
{ "_id" : ObjectId("5759658e654456bf4a014d04"), "a" : [ 0, 0, 4, 3, 2, 7 ] } 
+0

Giải pháp của bạn thật tuyệt vời. Tôi học được rất nhiều mongodb từ nó. Thks :) –

0

Sử dụng tập hợp.

Trong $match đường ống kết hợp, bạn có thể sử dụng $size$gte

+0

Tôi sẽ cố gắng, điều đó có thể khá hữu ích nếu nó hoạt động để tránh tiếp tục cập nhật trường "đếm"!Dunno lý do tại sao bạn đã downvoted tho, tôi upvote trở lại –

+0

@ libik: Tôi sẽ cung cấp cho nó một thử –

+0

Bạn không thể sử dụng '$ size' trong' $ match' ở đây. Tôi đã không thấy cách giải quyết vấn đề này ở đây. Btw @JulienLeray, bạn không upvote một câu trả lời chỉ vì nó đã được downvoted. Bình chọn dựa trên chất lượng của nội dung. – styvane

0

Bạn không cần phải có khuôn khổ đây nó khá đơn giản với JS. Tôi đã phải tạo ra một trường hợp thử nghiệm vì vậy hãy tha thứ cho đám đông. Chúng tôi phát minh ra một phương pháp Array mới. Array.prototype.intersect(). Nó sẽ cung cấp cho chúng ta các mục chung của hai mảng. Vì vậy, nếu chúng ta có hai đoạn văn bản, chúng ta có thể chèn một từ của mỗi từ (không trùng lặp) vào hai mảng và sau đó lấy một giao điểm của chúng. Hãy xem ...

Array.prototype.intersect = function(a) { 
 
    return this.filter(e => a.includes(e)); 
 
}; 
 
var text = "Last week we installed a kitty door so that our cat could come and go as she pleases. Unfortunately, we ran into a problem. Our cat was afraid to use the kitty door. We tried pushing her through, and that caused her to be even more afraid. The kitty door was dark, and she couldn’t see what was on the other side. The first step we took in solving this problem was taping the kitty door open. After a couple of days, she was confidently coming and going through the open door. However, when we removed the tape and closed the door, once again, she would not go through. They say you catch more bees with honey, so we decided to use food as bait. We would sit next to the kitty door with a can of wet food and click the top of the can. When kitty came through the closed door, we would open the can and feed her. It took five days of doing this to make her unafraid of using the kitty door. Now we have just one last problem; our kitty controls our lives!", 
 
    given = "People often install a kitty door, only to discover that they have a problem. The problem is their cat will not use the kitty door. There are several common reasons why cats won’t use kitty doors. First, they may not understand how a kitty door works. They may not understand that it is a little doorway just for them. Second, many kitty doors are dark and cats cannot see to the other side. As such, they can’t be sure of what is on the other side of the door, so they won’t take the risk. One last reason cats won’t use kitty doors is because some cats don’t like the feeling of pushing through and then having the door drag across their back. But don’t worry—there are solutions to this problem.\nThe first step in solving the problem is to prop the door open with tape. This means your cat will now be able to see through to the other side; your cat will likely begin using the kitty door immediately. Once your cat has gotten used to using the kitty door, remove the tape. Sometimes cats will continue to use the kitty door without any more prompting. If this does not happen, you will want to use food to bribe your cat. When it’s feeding time, sit on the opposite side of the door from your cat and either click the top of the can or crinkle the cat food bag. Open the door to show your cat that it is both you and the food waiting on the other side of the door. Repeat this a couple times, and then feed your cat. After a couple days of this, your kitty door problem will be gone.", 
 
// get one of each word of "text" lowercased and insert into textar 
 
    textar = Array.from(new Set(text.match(/\b\w+\b/g).map(e => e.toLowerCase()))), 
 
// get one of each word of "given" lowercased and insert into textar 
 
givenar = Array.from(new Set(given.match(/\b\w+\b/g).map(e => e.toLowerCase()))), 
 
    shared = givenar.intersect(textar); 
 
console.log(JSON.stringify(shared)); 
 
console.log(shared.length) // this is your result to decide upon.

+0

Tại sao bạn lại làm như vậy? Không, nghiêm túc. – styvane

+0

sr, nhưng có thể bạn đã hiểu lầm câu hỏi của tôi, đó là về truy vấn ở mongoose –

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