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:
-
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.
-
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?
-
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.
-
"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.