簡體   English   中英

如何在Node.js中高效/快速地執行數組連接,類似於MongoDB $ lookup?

[英]How to perform array join in Node.js efficiently/fast similar to MongoDB $lookup?

我想在Node.js中執行$ lookup,類似於MongoDB的$ lookup aggreation。

我有一個解決方案,但我不確定它在兩個數組中的每一個或更大的對象中使用更多對象的速度有多快。

let users = [
    {userId: 1, name: 'Mike'}, 
    {userId: 2, name: 'John'}
    ]
let comments = [
    {userId: 1, text: 'Hello'}, 
    {userId: 1, text: 'Hi'}, 
    {userId: 2, text: 'Hello'}
    ]

let commentsUsers = [
    {userId: 1, text: 'Hello', user: {userId: 1, name: 'Mike'}}, 
    {userId: 1, text: 'Hi', user: {userId: 1, name: 'Mike'}}, 
    {userId: 2, text: 'Hello', user: {userId: 2, name: 'John'}}
    ] //Desired result

我知道這可以通過ECMA6陣列輕松完成。 例如:

let commentsUsers = comments.map(comment => {comment, users.find(user => user.userId === comment.userId)} )

對於大量用戶來說,這是一種有效的方法,例如。 1M用戶。 lodash與這個或任何其他更專業的庫相比如何? 是否有更好的方法與香草JS這樣做,例如。 使用Array.prototype.reduce()? 可以以任何方式使用索引來提高連接的性能嗎?

編輯:

我的理想解決方案

 let users = [{userId:1,name:'Mike'},{userId:2,name:'John'}] let comments = [{userId:1,text:'Hello'},{userId:1,text:'Hi'},{userId:2,text:'Hello'}]; let usersMap = new Map(users.map(user => [user.userId, user])) let commentsUsers = comments.map(comment => ({...comment, user: usersMap.get(comment.userId)})) console.log(commentsUsers) 

感謝您的反饋!

您想要的結果不是正確的數據結構。 您缺少對象的關鍵字,例如{userId: 1, name: 'Mike'} 我添加了user作為索引解決方案的鍵值。

首先,我創建一個Map ,其中userId將成為我們的循環值。 之后,我只是使用map迭代comments ,將每個對象轉換為包含所有comment信息和新的kv用戶對象的新對象。 對於那對,我們不再需要使用find ,而是我們有一個簡單的HashMap get調用。

時間復雜度方面,這將代碼從O(n ^ 2)更改為O(n)

 let users = [{userId:1,name:'Mike'},{userId:2,name:'John'}], comments = [{userId:1,text:'Hello'},{userId:1,text:'Hi'},{userId:2,text:'Hello'}]; function mergeCommentUser(users, comments) { let map = new Map(users.map(v => [v.userId, v])); return comments.map(o => ({...o, user: map.get(o.userId)})); } console.log(JSON.stringify(mergeCommentUser(users,comments))) 

根據您的需要(以及節省冗余),您還可以更改以下行:

let map = new Map(users.map(v => [v.userId, v]));

改為:

let map = new Map(users.map(v => [v.userId, v.name]));

通過這樣你的結果看起來像:

[
    {"userId":1,"text":"Hello","user":"Mike"},
    {"userId":1,"text":"Hi","user":"Mike"},
    {"userId":2,"text":"Hello","user":"Paul"}
]

否則,您可以省略comment.userId ,而是將完整用戶添加到對象,以獲得另一種避免冗余的方法。

目前,您提供的代碼示例是O(n * m),或O(n 2 )。 您可以在users數組中創建每個userId及其各自索引的映射,然后您可以通過索引直接訪問它而不是查找用戶。 這將減少到O(n + m)的時間,即O(n)。

代碼看起來像這樣:

 const users = [{ userId: 1, name: "Mike" }, { userId: 2, name: "John" }]; const comments = [ { userId: 1, text: "Hello" }, { userId: 1, text: "Hi" }, { userId: 2, text: "Hello" } ]; const map = new Map(users.map((o, i) => [o.userId, i])); console.log( comments.map(o => { const index = map.get(o.userId); return index !== undefined ? { comment: o.text, user: users[index] } : o; }) ); 

顯然,您可以修改最終結果,但這種方法比您提出的方法更有效。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM