{"id":22775213,"url":"https://github.com/than-dev/recommendation-by-similarity","last_synced_at":"2025-03-30T13:14:42.998Z","repository":{"id":265466454,"uuid":"873112384","full_name":"than-dev/recommendation-by-similarity","owner":"than-dev","description":"An algorithm implementation to make content recommendations from similar users.","archived":false,"fork":false,"pushed_at":"2024-11-29T13:15:26.000Z","size":8,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-05T14:48:49.698Z","etag":null,"topics":["algorithms","development","javascript","logic","mathematics"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/than-dev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-10-15T16:10:01.000Z","updated_at":"2024-11-29T13:15:30.000Z","dependencies_parsed_at":"2024-11-29T14:27:00.027Z","dependency_job_id":"771b82ae-a4f7-4e76-b79f-714a464fba5e","html_url":"https://github.com/than-dev/recommendation-by-similarity","commit_stats":null,"previous_names":["than-dev/recommendation-by-similarity"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/than-dev%2Frecommendation-by-similarity","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/than-dev%2Frecommendation-by-similarity/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/than-dev%2Frecommendation-by-similarity/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/than-dev%2Frecommendation-by-similarity/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/than-dev","download_url":"https://codeload.github.com/than-dev/recommendation-by-similarity/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246320199,"owners_count":20758410,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["algorithms","development","javascript","logic","mathematics"],"created_at":"2024-12-11T18:26:26.866Z","updated_at":"2025-03-30T13:14:42.975Z","avatar_url":"https://github.com/than-dev.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Como a Netflix pega seus recomendados?\n\nSe você já se perguntou por que a Netflix recomenda séries que parecem ter sido feitas sob medida para o seu gosto, o \"culpado\" é um **algoritmo de similaridade**. Ele analisa seu comportamento e o compara com o de milhões de outros usuários para sugerir conteúdos que você provavelmente vai adorar. Vamos entender como isso funciona tecnicamente.\n\n### O que é um algoritmo de similaridade?\n\nImagine que a Netflix tem uma lista enorme de filmes e séries, além de dados sobre o que cada usuário já assistiu e gostou. O algoritmo de similaridade cruza essas informações para encontrar **padrões** entre você e outros usuários que têm gostos parecidos.\n\nDe maneira bem simplificada, ele olha para usuários que têm comportamentos de consumo similares ao seu (ou seja, pessoas que assistiram e gostaram dos mesmos conteúdos) e recomenda o que esses usuários viram e você ainda não.\n\n### Agora vamos para o nosso projeto!\n\nNosso objetivo aqui é criar um algoritmo que recomende posts (no caso de um streaming, filmes ou séries) para um usuário com base no comportamento de outros usuários semelhantes. O código que desenvolvemos busca resolver vários problemas típicos que surgem nesse tipo de tarefa.\n\n### comparar todos os usuários? Nem pensar!\n\nUm dos primeiros desafios que enfrentei foi: como comparar o comportamento de um usuário com **todos os outros** da plataforma? Isso não seria viável, especialmente se estivermos falando de milhares ou milhões de usuários. Para resolver isso, implementamos um filtro inicial que elimina grande parte dos usuários irrelevantes.\n\nNo código, a função `fillterUsers` faz exatamente isso:\n\n```jsx\n\nexport function filterUsers(allUsers, userId) {\n    const user = allUsers.find(({ id }) =\u003e id === userId);\n    const currentYear = new Date().getFullYear();\n\n    return allUsers.filter(({ country, lastAccess, id }) =\u003e {\n        const userLastAccessYear = new Date(lastAccess).getFullYear();\n        return (\n            country === user.country \u0026\u0026  // Mesma região\n            userLastAccessYear === currentYear \u0026\u0026  // Acesso recente\n            id !== user.id  // Excluir o próprio usuário\n        );\n    });\n}\n```\n\nAqui, restringimos os usuários que serão comparados aos que estão no **mesmo país** e que acessaram a plataforma no **mesmo ano**. Isso faz uma grande diferença, já que elimina uma enorme quantidade de dados desnecessários, focando apenas nas pessoas com mais chances de terem gostos similares ao do usuário em questão. Essa abordagem também garante que as recomendações sejam **mais relevantes**, já que as preferências podem variar muito entre diferentes países ou períodos de tempo.\n\n### E agora? Comparar preferências\n\nDepois de filtrar os usuários, precisamos comparar as preferências de quem restou com as do usuário atual. Para isso, criamos \"vetores\" que representam o comportamento de cada pessoa — ou seja, uma lista com tudo o que cada um assistiu ou interagiu. Assim, podemos ver quem tem gostos parecidos e determinar o nível de similaridade.\n\nA função `createUserVector` cuida de montar esses vetores com base no que o usuário assistiu. Aqui começa a mágica: a gente não precisa criar recomendações do zero, mas sim olhar para o que **outros usuários parecidos** já assistiram.\n\n```jsx\n\nconst userVector = createUserVector(userId, data.posts, data.reads);\n```\n\n### Lidando com grandes volumes de dados: um desafio constante\n\nOutro problema que enfrentamos foi o grande volume de dados, especialmente ao calcular as similaridades. Se tentássemos comparar todos os usuários restantes com todos os possíveis posts, isso se tornaria rapidamente **inviável**. Então, ao invés de calcular a similaridade para todos os itens, implementamos um sistema de **threshold** (limite) para focar apenas nos usuários que realmente têm um nível mínimo de similaridade.\n\n```jsx\n\nfunction applyThresholdAndSort(similarities, threshold) {\n    return similarities\n        .filter(({ similarity }) =\u003e similarity \u003e threshold)  // Aplica o threshold\n        .sort((a, b) =\u003e b.similarity - a.similarity);  // Ordena por maior similaridade\n}\n\n```\n\nIsso evita que o sistema perca tempo com usuários que têm pouca ou nenhuma semelhança, focando apenas nos casos que realmente importam.\n\n### Selecionando as melhores recomendações\n\nDepois de calcular a similaridade, pegamos os usuários mais parecidos e, finalmente, chegamos ao ponto onde fazemos as recomendações. Aqui, garantimos que os posts recomendados sejam aqueles que o usuário **ainda não viu** — afinal, de nada adianta recomendar algo que ele já assistiu.\n\n```jsx\n\nfunction getRecommendations(similarUserIds, userVector, reads) {\n    return reads\n        .filter(\n            (read) =\u003e\n                similarUserIds.includes(read.userId) \u0026\u0026\n                !userVector[read.postId - 1]  // Verifica se o post já foi visto\n        )\n        .map((read) =\u003e read.postId);\n}\n\n```\n\nEsse trecho garante que as recomendações sejam **novas** para o usuário e estejam de acordo com os gostos de pessoas com interesses parecidos.\n\n### Evitando duplicatas\n\nOutro ponto importante foi evitar **recomendações duplicadas**. Ao lidar com grandes volumes de dados, é fácil acabar sugerindo o mesmo conteúdo mais de uma vez. Para resolver isso, usamos um simples método de remoção de duplicatas:\n\n```jsx\n\nfunction removeDuplicates(recommendations) {\n    return [...new Set(recommendations)];\n}\n\n```\n\nEsse pequeno ajuste garante que o usuário receba uma lista mais diversificada e sem repetição de conteúdos.\n\n### Conclusão\n\nCom esses passos, conseguimos construir um sistema de recomendação eficiente, que filtra, compara e sugere conteúdos de maneira otimizada. O segredo está em fazer escolhas estratégicas, como filtrar usuários e focar nas similaridades mais relevantes. Assim, o algoritmo se torna ágil e preciso, evitando o desperdício de recursos e garantindo uma experiência personalizada para cada usuário.\n\nNa próxima vez que a Netflix te recomendar aquela série que parece perfeita para você, saiba que, por trás disso, há todo um processo técnico que envolve filtros inteligentes, cálculo de similaridade e otimização de dados — tudo pensado para oferecer a melhor recomendação possível!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthan-dev%2Frecommendation-by-similarity","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthan-dev%2Frecommendation-by-similarity","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthan-dev%2Frecommendation-by-similarity/lists"}