2016-06-09 33 views
5

È fondamentalmente ciò che dice il titolo.Trova documenti il ​​cui campo array contiene almeno n elementi di un determinato array

ingresso: myArray = un array di parole

Ho un modello che ha campo wordsCollection, che è un campo di matrice.

Come posso trovare tutti i documenti di quel modello la cui wordsCollections ha almeno n elementi di myArray

+0

struttura Visualizza db e quali anni hanno cercato finora di farlo funzionare. – Shrabanee

+0

Non penso che la domanda sia abbastanza chiara che non ho bisogno di fornire la struttura db. Non sono sicuro che mongodb fornisca una tale chiamata API, quindi sto solo pensando di iterare attraverso tutti i documenti .... Ovviamente, suona davvero male –

+0

Gli elementi di 'myArray' e' wordsCollection' sono unici? – Redu

risposta

3

Let dire che abbiamo i seguenti documenti in nostra collezione:

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

e la seguente matrice di ingresso e n = 2

var inputArray = [1, 3, 0]; 

Possiamo restituire quei documenti in cui il campo dell'array contiene almeno n elementi di un dato array usando la struttura di aggregazione.

Il $match seleziona solo quei documenti con lunghezza della matrice maggiore o uguale a n. Ciò riduce la quantità di dati da elaborare in fondo alla pipeline.

Il $redact operatore pipeline utilizzano un'elaborazione condizione logica usando l'operatore $cond e le operazioni speciali $$KEEP a "mantenere" il documento in cui la condizione logica è vera o $$PRUNE a "disfarsi" del documento in cui la condizione è falsa.

Nel nostro caso, la condizione è $gte che restituisce vero se la $size dell'intersezione delle due matrici che calcoliamo usando l'operatore $setIntersection è maggiore o uguale 2.

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

che produce:

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

La tua soluzione è sorprendente. Imparo molto mongodb da esso. Thks :) –

0

Usa aggregazione.

In $match aggregazione cantiere, è possibile utilizzare $size e $gte

+0

Ci proverò, potrebbe essere molto utile se è un lavoro evitare di continuare ad aggiornare il campo "conta"!Non so perché hai downvoted tho, investo di nuovo –

+0

@libik: ci provo io –

+0

Non puoi usare '$ size' in' $ match' qui. Non sono riuscito a vedere come questo risolva il problema qui. Btw @JulienLeray, non invii una risposta solo perché è stata downvoted. Vota in base alla qualità del contenuto. – styvane

0

Non ho bisogno di nessun quadro qui è abbastanza semplice con JS. Ho dovuto creare un caso di prova quindi per favore perdona la folla. Inventiamo un nuovo metodo di array. Array.prototype.intersect(). Ci darà gli elementi comuni di due array. Quindi, se abbiamo due paragrafi di testo, possiamo inserire una parola per ogni parola (senza duplicati) in due matrici e quindi prendere un'intersezione tra di esse. Vediamo ...

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

Perché lo farai così? No sul serio. – styvane

+0

sr, ma forse hai frainteso la mia domanda, si tratta di query in mangusta –