MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Come trovare documenti con esattamente le stesse voci di matrice di una query

Ci sono diversi "casi molto utili" qui in cui in effetti il ​​tentativo di creare un "hash unico" sul contenuto dell'array sta effettivamente "mettendo in mezzo" la miriade di problemi che possono essere facilmente risolti.

Trovare cose comuni a "me"

Se ad esempio prendi "utente 1" dall'esempio fornito e consideri di avere già caricato quei dati e vuoi trovare "quelli in comune con me" in base agli "itemsIds" corrispondenti da ciò che ha l'oggetto utente corrente, allora lì sono due semplici approcci di query:

  1. Trova "esattamente" lo stesso: È dove vuoi esaminare i dati di altri utenti per vedere quegli utenti che hanno gli stessi interessi "esatti". Questo è un utilizzo semplice e "non ordinato" di $all operatore di query:

    db.collection.find({ 
        "itemsIds": { "$all": [399957190, 366369952] },
        "userId": { "$ne": 1 }
    })
    

    Che restituirà "utente 3" poiché sono quelli con "entrambe" voci comuni "itemsIds". L'ordine non è importante qui in quanto è sempre una corrispondenza in qualsiasi ordine, purché ci siano entrambi. Questa è un'altra forma di $and come argomenti di query.

  2. Trova "simile" in comune a me": Che fondamentalmente sta chiedendo "hai qualcosa che è lo stesso?" . Per questo puoi usare $in operatore di interrogazione. Corrisponderà se "una delle condizioni specificate è soddisfatta:

    db.collection.find({ 
        "itemsIds": { "$in": [399957190, 366369952] },
        "userId": { "$ne": 1 }
    })
    

    In questo caso "sia" "utente 2" che "utente 3" corrisponderanno, poiché "almeno" condividono "una" delle condizioni specificate e ciò significa che hanno "qualcosa in comune" con i dati di origine di la domanda.

    Questa è in effetti un'altra forma di $or operatore di query, e proprio come prima è molto più semplice e conciso scrivere in questo modo date le condizioni da applicare.

Trovare "cose" comuni

Ci sono anche casi in cui potresti voler trovare cose "in comune" senza avere un "utente" di base da cui partire. Quindi, come fai a dire che "utente 1" e "utente 2" condividono gli stessi "itemIds", o in effetti che vari utenti potrebbero condividere lo stesso valore "itemIds" individualmente, ma chi sono?

  1. Ottieni le corrispondenze esatte: È ovviamente dove guardi i valori "itemsIds" e $group loro insieme. Generalmente l'"ordine è importante" qui, quindi in modo ottimale li hai "preordinati" e sempre in modo coerente per renderlo semplice come:

    db.collection.aggregate([
        { "$group": {
            "_id": "$itemsIds",
            "common": { "$push": "$userId" }
        }}
    ])
    

    E questo è tutto ciò che c'è veramente da fare, fintanto che l'ordine è già lì. In caso contrario, puoi eseguire un modulo leggermente più lungo per eseguire "l'ordinamento", ma lo stesso si potrebbe dire della generazione di un "hash":

    db.collection.aggregate([
        { "$unwind": "$itemsIds" },
        { "$sort": { "_id": 1, "itemsIds": 1 } },
        { "$group": {
            "_id": "$_id",
            "userId": { "$first": "$userId" },
            "itemsIds": { "$push": "$itemsIds" }
        }},
        { "$group": {
            "_id": "$itemsIds",
            "common": { "$push": "$userId" }
        }}
    ])
    

    Non "super" performante, ma rende evidente il motivo per cui mantieni sempre ordinato l'aggiunta di voci di array. Che è un processo molto semplice.

  2. "utente" comune a "items": Che è un altro semplice processo che astrae sopra con "scomporre" l'array in $unwind , e quindi sostanzialmente raggruppando:

    db.collection.aggregate([
        { "$unwind": "$itemsIds" },
        { "$group": {
            "_id": "$itemsIds",
            "users": { "$addToSet": "$userId" }
        }}
    ])
    

    E ancora, solo un semplice aggregatore di raggruppamento di $addToSet fa il lavoro e raccoglie i valori "distinct userId" per ogni valore "itemsIds".

Queste sono tutte soluzioni di base e potrei continuare con "impostare le intersezioni" e cosa no, ma questo è il "primer".

Non provare a calcolare un "hash", MongoDB ha comunque un buon "arsenale" per abbinare le voci. Usalo e anche "abusa di esso", fino a quando non si rompe. Quindi prova di più.