2016-06-09 28 views
5

Jest to w zasadzie to, co mówi tytuł.Znajdź dokumenty, których pole tablicy zawiera co najmniej n elementów danej tablicy

Wejście: myArray = tablicę słów

Mam modelu, które mają pole wordsCollection, która jest polem tablicą.

Jak mogę znaleźć wszystkie dokumenty dotyczące tego modelu, którego wordsCollections ma co najmniej n elementów myArray

+0

struktura Pokaż db i co yo próbowałem tak daleko, aby to działało. – Shrabanee

+0

Nie sądzę, że pytanie jest wystarczająco jasne, że nie muszę podawać struktury db. Nie jestem pewien, czy mongodb zapewnia takie wywołanie API, więc po prostu myślę o iteracji przez wszystkie dokumenty ... Oczywiście, brzmi naprawdę źle –

+0

Czy elementy 'myArray' i' wordsCollection' są unikatowe? – Redu

Odpowiedz

3

powiedzmy mamy następujące dokumenty w naszej kolekcji:

{ "_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 ] } 

i następującą tablicę wejściowych i n = 2

var inputArray = [1, 3, 0]; 

Możemy zwrócić te dokumenty, w których pole tablicy zawiera co najmniej n elementów danej tablicy przy użyciu struktury agregacji.

Urządzenie $match wybiera tylko te dokumenty, które mają większą długość tablicy lub są równe n. Zmniejsza to ilość danych do przetworzenia w dół w potoku.

$redact operator rurociągu użyć logicznego przetwarzania warunku pomocą operatora $cond i operacje specjalne $$KEEP aby „zachować” dokument, w którym warunek logiczny jest prawdziwy lub $$PRUNE do „wyrzucić” dokument gdzie warunek jest fałszywy.

W naszym przypadku, warunek jest $gte która zwraca true jeśli $size skrzyżowania dwóch tablic, które możemy obliczyć za pomocą operatora $setIntersection jest większa lub równa 2.

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

która produkuje:

{ "_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

Twoje rozwiązanie jest niesamowite. Uczę się od niego wielu monondów. Thks :) –

0

Korzystanie agregacji.

W $match agregacji rurociągu, można użyć $size i $gte

+0

Spróbuję, to może być całkiem przydatne, jeśli to działa, aby uniknąć aktualizowania pola "liczenia"!Dunno, dlaczego zostałeś cenzurowany, przegłosowałem: –

+0

@libik: Spróbuję. –

+0

Nie możesz użyć '$ size' w' $ match' tutaj. Nie widziałem, jak to rozwiązuje problem tutaj. Btw @JulienLeray, nie udzielasz odpowiedzi tylko dlatego, że została cofnięta. Głosuj na podstawie jakości treści. – styvane

0

Nie trzeba żadnych ram tutaj jest dość proste z JS. Musiałem stworzyć przypadek testowy, więc proszę wybaczyć tłumowi. Wynaleźliśmy nową metodę Array. Array.prototype.intersect(). Da nam wspólne elementy dwóch tablic. Jeśli więc mamy dwa akapity tekstowe, możemy wstawić jedno z każdego słowa (bez duplikatów) do dwóch tablic, a następnie je skrzyżować. Zobaczmy ...

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

Dlaczego to zrobisz? Niepoważnie. – styvane

+0

sr, ale może źle zrozumiałeś moje pytanie, chodzi o zapytanie w mangurze –