MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Como encontrar documentos com exatamente as mesmas entradas de matriz que em uma consulta


Existem vários "casos muito úteis" aqui em que, na verdade, tentar criar um "hash único" sobre o conteúdo do array está, na verdade, "atrapalhando" a miríade de problemas que podem ser facilmente resolvidos.

Encontrando Comum para "Eu"


Se você, por exemplo, pegar "usuário 1" do exemplo fornecido e considerar que já carregou esses dados e deseja encontrar "aqueles em comum comigo" pelos "itemsIds" correspondentes do objeto de usuário atual, então são duas abordagens de consulta simples:

  1. Encontre "exatamente" o mesmo: É onde você deseja inspecionar os dados de outros usuários para ver os usuários que têm os mesmos interesses "exatos". Este é um uso simples e "não ordenado" do $todos operador de consulta:
    db.collection.find({ 
        "itemsIds": { "$all": [399957190, 366369952] },
        "userId": { "$ne": 1 }
    })
    

    Que vai retornar "usuário 3", já que eles são os únicos com "ambos" entradas "itemsIds" comuns. A ordem não é importante aqui, pois é sempre uma correspondência em qualquer ordem, desde que ambos estejam lá. Esta é outra forma de $and como argumentos de consulta.

  2. Encontre "semelhante" em comum para mim": O que é basicamente perguntar "você tem algo igual?" . Para isso, você pode usar o $in operador de consulta. Ele corresponderá se "qualquer uma" das condições especificadas for atendida:
    db.collection.find({ 
        "itemsIds": { "$in": [399957190, 366369952] },
        "userId": { "$ne": 1 }
    })
    

    Neste caso, "ambos" o "usuário 2" e o "usuário 3" vão corresponder, pois "ao menos" compartilham "uma" das condições especificadas e isso significa que têm "algo em comum" com os dados de origem de A pergunta.

    Esta é, na verdade, outra forma do $or operador de consulta e, como antes, é muito mais simples e conciso escrever dessa maneira, dadas as condições a serem aplicadas.

Encontrando "coisas" comuns


Há também casos em que você pode querer encontrar coisas "em comum" sem ter um "usuário" básico para começar. Então, como você diz que "usuário 1" e "usuário 2" compartilham os mesmos "itemIds" ou, de fato, vários usuários podem compartilhar o mesmo valor "itemIds" individualmente, mas quem são eles?

  1. Obtenha as correspondências exatas: É claro que você vê os valores "itemsIds" e $grupo eles juntos. Geralmente, o "pedido é importante" aqui, portanto, você os tem "pré-encomendados" e consistentemente sempre para tornar isso tão simples quanto:
    db.collection.aggregate([
        { "$group": {
            "_id": "$itemsIds",
            "common": { "$push": "$userId" }
        }}
    ])
    

    E isso é tudo o que realmente existe, desde que a ordem já esteja lá. Caso contrário, você pode fazer um formulário um pouco mais longo para fazer o "ordenamento", mas o mesmo pode ser dito para gerar um "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" }
        }}
    ])
    

    Não tem um desempenho "super", mas mostra o motivo pelo qual você sempre mantém a ordem na adição de entradas de matriz. O que é um processo muito simples.

  2. "usuário" comum a "itens": Que é outro processo simples abstraindo acima com "quebrando" a matriz em $unwind , e então basicamente agrupando de volta:
    db.collection.aggregate([
        { "$unwind": "$itemsIds" },
        { "$group": {
            "_id": "$itemsIds",
            "users": { "$addToSet": "$userId" }
        }}
    ])
    

    E, novamente, apenas um simples agregador de agrupamento de $ addToSet faz o trabalho e coleta os valores "distinct userId" para cada valor "itemsIds".

Estas são todas as soluções básicas, e eu poderia continuar com "interseções definidas" e outras coisas, mas esta é a "cartilha".

Não tente calcular um "hash", o MongoDB tem um bom "arsenal" para combinar as entradas de qualquer maneira. Use e "abuse" também, até quebrar. Então tente mais.