[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"navigation":3,"url-settings":86,"blog-\u002Fblog\u002Fentity-resolution-with-data-flow":671,"blog-author-\u002Fblog\u002Fentity-resolution-with-data-flow":1190,"i-material-symbols:arrow-back-rounded":1202},{"id":4,"extension":5,"footer":6,"header":73,"meta":83,"stem":84,"__hash__":85},"navigation\u002Fdata\u002Fshared\u002Fnavigation.yml","yml",{"brand":7,"columns":13,"legal":63},{"name":8,"tagline":9,"downloadCta":10},"Pieces","The memory layer for modern work.",{"label":11,"href":12},"All downloads","\u002Fdownloads",[14,26,39,51],{"title":15,"links":16},"Product",[17,20,23],{"label":18,"href":19},"Pieces Desktop","\u002F",{"label":21,"href":22},"Pieces Enterprise","\u002Fenterprise",{"label":24,"href":25},"Pieces MCP","\u002Fmcp",{"title":27,"links":28},"Resources",[29,33,36],{"label":30,"href":31,"external":32},"Documentation","url:docs.home",true,{"label":34,"href":35},"Blog","\u002Fblog",{"label":37,"href":38,"external":32},"GitHub","url:github.org",{"title":40,"links":41},"Community",[42,45,48],{"label":43,"href":44,"external":32},"Discord","url:social.discord",{"label":46,"href":47,"external":32},"X \u002F Twitter","url:social.x",{"label":49,"href":50,"external":32},"LinkedIn","url:social.linkedin",{"title":52,"links":53},"Company",[54,57,60],{"label":55,"href":56},"About","\u002Fabout",{"label":58,"href":59},"Updates","\u002Fupdates",{"label":61,"href":62},"Contact","\u002Fcontact",[64,67,70],{"label":65,"href":66},"Privacy Policy","\u002Flegal\u002Fprivacy",{"label":68,"href":69},"Refund Policy","\u002Flegal\u002Frefund",{"label":71,"href":72},"Terms of Service","\u002Flegal\u002Fterms",{"links":74,"signIn":75,"contact":78,"cta":80},[],{"label":76,"href":77},"Manage account","url:portal.home",{"label":79,"href":62},"Get in touch",{"label":81,"href":82},"Download","url:routes.downloads",{},"data\u002Fshared\u002Fnavigation","XlSALC7vYCXHcmcXnjJViwIZKsqnQWF4bn4o9RrcSBE",{"id":87,"extension":5,"links":88,"meta":668,"stem":669,"__hash__":670},"urlSettings\u002Fdata\u002Fshared\u002Furls.yml",[89,93,97,101,105,109,113,117,121,125,129,133,137,141,145,149,153,157,161,165,169,173,177,181,185,189,192,196,200,204,208,212,216,220,224,228,232,236,240,244,248,252,256,260,264,268,272,276,280,284,288,292,296,300,303,307,311,314,318,322,326,330,334,338,342,346,350,354,358,362,366,370,374,378,382,386,390,394,398,402,406,410,414,418,422,426,430,434,438,442,446,450,454,458,461,465,469,473,477,481,485,488,491,494,497,501,505,508,512,516,520,524,528,532,536,540,544,548,552,556,559,563,567,571,575,579,582,585,588,592,595,599,603,607,611,614,618,622,625,628,631,635,639,643,646,649,652,656,660,664],{"key":90,"label":91,"href":92},"downloads.desktop","Desktop download page","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fdownload",{"key":94,"label":95,"href":96},"downloads.macOS.dmgArm64","macOS DMG Apple Silicon","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_for_x\u002Fdmg-arm64\u002Fdownload",{"key":98,"label":99,"href":100},"downloads.macOS.dmgIntel","macOS DMG Intel","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_for_x\u002Fdmg\u002Fdownload",{"key":102,"label":103,"href":104},"downloads.macOS.pkg","macOS PKG","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fmacos_packaging\u002Fpkg\u002Fdownload",{"key":106,"label":107,"href":108},"downloads.macOS.universal","Desktop macOS Universal","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_for_x\u002Fmacos-universal\u002Fdownload",{"key":110,"label":111,"href":112},"downloads.macOS.pkgArm64","Desktop macOS PKG Apple Silicon","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fmacos_packaging\u002Fpkg-pfd-arm64\u002Fdownload",{"key":114,"label":115,"href":116},"downloads.macOS.pkgIntel","Desktop macOS PKG Intel","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fmacos_packaging\u002Fpkg-pfd\u002Fdownload",{"key":118,"label":119,"href":120},"downloads.windows.appinstaller","Windows App Installer","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fappinstaller\u002Fpieces_for_x.appinstaller",{"key":122,"label":123,"href":124},"downloads.windows.exe","Windows EXE","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_for_x\u002Fwindows-exe\u002Fdownload",{"key":126,"label":127,"href":128},"downloads.windows.msix","Windows MSIX","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_for_x\u002Fwindows-msix\u002Fdownload",{"key":130,"label":131,"href":132},"downloads.windows.suiteManager","Windows Suite Manager","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_suite_windows\u002Fappinstaller\u002Fdownload",{"key":134,"label":135,"href":136},"downloads.linux.flatpakRepo","Linux Flatpak repository","https:\u002F\u002Fbuilds.pieces.app\u002Fpieces-flatpak-repo\u002Fpieces-flatpak.flatpakrepo",{"key":138,"label":139,"href":140},"downloads.linux.snapDesktop","Linux Snap Desktop","https:\u002F\u002Fsnapcraft.io\u002Fpieces-for-developers",{"key":142,"label":143,"href":144},"downloads.linux.snapPiecesOS","Linux Snap PiecesOS","https:\u002F\u002Fsnapcraft.io\u002Fpieces-os",{"key":146,"label":147,"href":148},"downloads.linux.snap","Desktop Linux Snap package","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_for_x\u002Fsnap\u002Fdownload",{"key":150,"label":151,"href":152},"downloads.piecesOS.macOS.dmgArm64","PiecesOS macOS DMG Apple Silicon","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fos_server\u002Fdmg-arm64\u002Fdownload",{"key":154,"label":155,"href":156},"downloads.piecesOS.macOS.dmgIntel","PiecesOS macOS DMG Intel","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fos_server\u002Fdmg\u002Fdownload",{"key":158,"label":159,"href":160},"downloads.piecesOS.macOS.universal","PiecesOS macOS Universal","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fos_server\u002Fmacos-universal\u002Fdownload",{"key":162,"label":163,"href":164},"downloads.piecesOS.macOS.pkgArm64","PiecesOS macOS PKG Apple Silicon","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fmacos_packaging\u002Fpkg-pos-launch-only-arm64\u002Fdownload",{"key":166,"label":167,"href":168},"downloads.piecesOS.macOS.pkgIntel","PiecesOS macOS PKG Intel","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fmacos_packaging\u002Fpkg-pos-launch-only\u002Fdownload",{"key":170,"label":171,"href":172},"downloads.piecesOS.windows.appinstaller","PiecesOS Windows App Installer","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fappinstaller\u002Fos_server.appinstaller",{"key":174,"label":175,"href":176},"downloads.piecesOS.windows.exe","PiecesOS Windows EXE","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fos_server\u002Fwindows-exe\u002Fdownload",{"key":178,"label":179,"href":180},"downloads.piecesOS.windows.msix","PiecesOS Windows MSIX","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fos_server\u002Fwindows-msix\u002Fdownload",{"key":182,"label":183,"href":184},"downloads.piecesOS.linux.snap","PiecesOS Linux Snap package","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fos_server\u002Fsnap\u002Fdownload",{"key":186,"label":187,"href":188},"downloads.combined.macOS.appleSilicon","Combined macOS installer Apple Silicon","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fmacos_packaging\u002Fpkg-arm64\u002Fdownload",{"key":190,"label":191,"href":104},"downloads.combined.macOS.intel","Combined macOS installer Intel",{"key":193,"label":194,"href":195},"downloads.guides.macOS","macOS installation guide","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Fmacos-installation-guide",{"key":197,"label":198,"href":199},"downloads.guides.windows","Windows installation guide","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Fwindows-installation-guide",{"key":201,"label":202,"href":203},"downloads.guides.linux","Linux installation guide","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Flinux-installation-guide",{"key":205,"label":206,"href":207},"downloads.guides.linuxFlatpak","Linux Flatpak installation guide","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Flinux-installation-guide\u002Fflatpak",{"key":209,"label":210,"href":211},"downloads.guides.linuxSnap","Linux Snap installation guide","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Flinux-installation-guide\u002Fsnap",{"key":213,"label":214,"href":215},"downloads.guides.piecesOS","PiecesOS manual installation","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies\u002Fpieces-os\u002Fmanual-installation",{"key":217,"label":218,"href":219},"extensions.chrome","Chrome extension","https:\u002F\u002Fchrome.google.com\u002Fwebstore\u002Fdetail\u002Fpieces-save-code-snippets\u002Figbgibhbfonhmjlechmeefimncpekepm",{"key":221,"label":222,"href":223},"extensions.firefox","Firefox add-on","https:\u002F\u002Faddons.mozilla.org\u002Fen-US\u002Ffirefox\u002Faddon\u002Fpieces-save-code-from-the-web\u002F",{"key":225,"label":226,"href":227},"extensions.edge","Edge add-on","https:\u002F\u002Fmicrosoftedge.microsoft.com\u002Faddons\u002Fdetail\u002Fpieces-save-code-snippet\u002Fhglfimcdgonaeeobjckfdabcldfidmim",{"key":229,"label":230,"href":231},"extensions.vscode","VS Code extension","https:\u002F\u002Fmarketplace.visualstudio.com\u002Fitems?itemName=MeshIntelligentTechnologiesInc.pieces-vscode",{"key":233,"label":234,"href":235},"extensions.visualStudio","Visual Studio extension","https:\u002F\u002Fmarketplace.visualstudio.com\u002Fitems?itemName=MeshIntelligentTechnologiesInc.PiecesVisualStudio",{"key":237,"label":238,"href":239},"extensions.jetbrains","JetBrains plugin","https:\u002F\u002Fplugins.jetbrains.com\u002Fplugin\u002F17328-pieces--save-search-share--reuse-code-snippets",{"key":241,"label":242,"href":243},"extensions.obsidian","Obsidian plugin","https:\u002F\u002Fobsidian.md\u002Fplugins?id=pieces-for-developers",{"key":245,"label":246,"href":247},"extensions.sublime","Sublime package","https:\u002F\u002Fpackagecontrol.io\u002Fpackages\u002FPieces",{"key":249,"label":250,"href":251},"extensions.neovim","Neovim plugin","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fplugin_neo_vim",{"key":253,"label":254,"href":255},"extensions.jupyterlab","JupyterLab plugin","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fjupyterlab-pieces",{"key":257,"label":258,"href":259},"extensions.cli","Pieces CLI","https:\u002F\u002Fpypi.org\u002Fproject\u002Fpieces-cli\u002F",{"key":261,"label":262,"href":263},"docs.home","Documentation home","https:\u002F\u002Fdocs.pieces.app",{"key":265,"label":266,"href":267},"docs.getStarted","Get started docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces",{"key":269,"label":270,"href":271},"docs.api","API docs","https:\u002F\u002Fdocs.pieces.app\u002Fapi",{"key":273,"label":274,"href":275},"docs.desktop.overview","Desktop overview","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop",{"key":277,"label":278,"href":279},"docs.desktop.onboarding","Desktop onboarding","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fonboarding",{"key":281,"label":282,"href":283},"docs.desktop.timeline","Desktop timeline docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Ftimeline",{"key":285,"label":286,"href":287},"docs.desktop.summaries","Desktop summaries docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fsingle-click-summaries",{"key":289,"label":290,"href":291},"docs.desktop.search","Desktop conversational search docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fconversational-search",{"key":293,"label":294,"href":295},"docs.desktop.drive","Desktop drive docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fdrive",{"key":297,"label":298,"href":299},"docs.desktop.account","Desktop account settings docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fconfiguration\u002Faccount",{"key":301,"label":302,"href":92},"docs.desktop.download","Desktop download docs",{"key":304,"label":305,"href":306},"docs.piecesOS.overview","PiecesOS overview docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies",{"key":308,"label":309,"href":310},"docs.piecesOS.details","PiecesOS details docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies\u002Fpieces-os",{"key":312,"label":313,"href":215},"docs.piecesOS.install","PiecesOS install docs",{"key":315,"label":316,"href":317},"docs.piecesOS.quickMenu","PiecesOS quick menu docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies\u002Fpieces-os\u002Fquick-menu",{"key":319,"label":320,"href":321},"docs.piecesOS.storage","On-device storage docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies\u002Fon-device-storage",{"key":323,"label":324,"href":325},"docs.piecesOS.troubleshooting","PiecesOS troubleshooting docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies\u002Fpieces-os\u002Ftroubleshooting",{"key":327,"label":328,"href":329},"docs.mcp.overview","MCP overview docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp",{"key":331,"label":332,"href":333},"docs.mcp.cursor","MCP Cursor docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fcursor",{"key":335,"label":336,"href":337},"docs.mcp.vscode","MCP VS Code docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fvs-code",{"key":339,"label":340,"href":341},"docs.mcp.claudeDesktop","MCP Claude Desktop docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fclaude-desktop",{"key":343,"label":344,"href":345},"docs.mcp.claudeCode","MCP Claude Code docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fclaude-code",{"key":347,"label":348,"href":349},"docs.mcp.claudeCowork","MCP Claude Cowork docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fclaude-cowork",{"key":351,"label":352,"href":353},"docs.mcp.githubCopilot","MCP GitHub Copilot docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fgithub-copilot",{"key":355,"label":356,"href":357},"docs.mcp.goose","MCP Goose docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fgoose",{"key":359,"label":360,"href":361},"docs.mcp.windsurf","MCP Windsurf docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fwindsurf",{"key":363,"label":364,"href":365},"docs.mcp.zed","MCP Zed docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fzed",{"key":367,"label":368,"href":369},"docs.mcp.jetbrains","MCP JetBrains docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fjetbrains-ides",{"key":371,"label":372,"href":373},"docs.mcp.continueDev","MCP Continue docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fcontinue-dev",{"key":375,"label":376,"href":377},"docs.mcp.cline","MCP Cline docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fcline",{"key":379,"label":380,"href":381},"docs.mcp.raycast","MCP Raycast docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fraycast",{"key":383,"label":384,"href":385},"docs.mcp.rovoDevCli","MCP Rovo Dev CLI docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Frovo-dev-cli",{"key":387,"label":388,"href":389},"docs.mcp.openaiCodexCli","MCP OpenAI Codex CLI docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fopenai-codex-cli",{"key":391,"label":392,"href":393},"docs.mcp.googleGeminiCli","MCP Google Gemini CLI docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fgoogle-gemini-cli",{"key":395,"label":396,"href":397},"docs.mcp.amazonQ","MCP Amazon Q docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Famazon-q-developer",{"key":399,"label":400,"href":401},"docs.mcp.chatgptDev","MCP ChatGPT Developer Mode docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fchatgpt-developer-mode",{"key":403,"label":404,"href":405},"docs.mcp.openclaw","MCP OpenClaw docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fopenclaw",{"key":407,"label":408,"href":409},"docs.mcp.mcpRemote","MCP Remote docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fmcp-remote",{"key":411,"label":412,"href":413},"docs.mcp.ngrok","MCP ngrok docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fngrok-setup",{"key":415,"label":416,"href":417},"docs.troubleshooting.macOS","macOS troubleshooting docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Ftroubleshooting\u002Fmacos",{"key":419,"label":420,"href":421},"docs.troubleshooting.windows","Windows troubleshooting docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Ftroubleshooting\u002Fwindows",{"key":423,"label":424,"href":425},"docs.troubleshooting.linux","Linux troubleshooting docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Ftroubleshooting\u002Flinux",{"key":427,"label":428,"href":429},"docs.privacy","Privacy and security docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fprivacy-security-your-data",{"key":431,"label":432,"href":433},"docs.support","Support docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fsupport",{"key":435,"label":436,"href":437},"portal.home","Pieces portal","https:\u002F\u002Fportal.pieces.app",{"key":439,"label":440,"href":441},"site.home","Website home","https:\u002F\u002Fpieces.app",{"key":443,"label":444,"href":445},"site.about","About page","https:\u002F\u002Fpieces.app\u002Fabout",{"key":447,"label":448,"href":449},"site.features","Features page","https:\u002F\u002Fpieces.app\u002Ffeatures",{"key":451,"label":452,"href":453},"site.plugins","Plugins page","https:\u002F\u002Fpieces.app\u002Fplugins",{"key":455,"label":456,"href":457},"site.contact","Contact page","https:\u002F\u002Fpieces.app\u002Fcontact",{"key":459,"label":58,"href":460},"site.updates","https:\u002F\u002Fpieces.app\u002Fupdates",{"key":462,"label":463,"href":464},"site.news","News","https:\u002F\u002Fpieces.app\u002Fnews",{"key":466,"label":467,"href":468},"site.events","Community events","https:\u002F\u002Fpieces.app\u002Fcommunity\u002Fevents",{"key":470,"label":471,"href":472},"site.userStories","User stories","https:\u002F\u002Fpieces.app\u002Fuser-stories",{"key":474,"label":475,"href":476},"site.academy","Academy","https:\u002F\u002Fpieces.app\u002Flearn\u002Facademy",{"key":478,"label":479,"href":480},"site.support","Website support","https:\u002F\u002Fpieces.app\u002Fsupport",{"key":482,"label":483,"href":484},"site.standup","Standup","https:\u002F\u002Fpieces.app\u002Fstandup",{"key":486,"label":34,"href":487},"site.blog","https:\u002F\u002Fcode.pieces.app\u002Fblog",{"key":489,"label":43,"href":490},"social.discord","https:\u002F\u002Fdiscord.gg\u002Fgetpieces",{"key":492,"label":46,"href":493},"social.x","https:\u002F\u002Fx.com\u002Fgetpieces",{"key":495,"label":496,"href":493},"social.twitter","Twitter",{"key":498,"label":499,"href":500},"social.instagram","Instagram","https:\u002F\u002Fwww.instagram.com\u002Fgetpieces\u002F",{"key":502,"label":503,"href":504},"social.tiktok","TikTok","https:\u002F\u002Fwww.tiktok.com\u002F@getpieces",{"key":506,"label":49,"href":507},"social.linkedin","https:\u002F\u002Fwww.linkedin.com\u002Fcompany\u002Fgetpieces\u002F",{"key":509,"label":510,"href":511},"social.youtube","YouTube","https:\u002F\u002Fyoutube.com\u002F@getpieces",{"key":513,"label":514,"href":515},"github.org","GitHub organization","https:\u002F\u002Fgithub.com\u002Fpieces-app",{"key":517,"label":518,"href":519},"github.support","GitHub support","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fsupport",{"key":521,"label":522,"href":523},"github.issues","GitHub issues","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fsupport\u002Fissues",{"key":525,"label":526,"href":527},"github.discussions","GitHub discussions","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fsupport\u002Fdiscussions",{"key":529,"label":530,"href":531},"github.documentation","GitHub documentation","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fdocumentation",{"key":533,"label":534,"href":535},"github.opensource","GitHub open source","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fopensource",{"key":537,"label":538,"href":539},"github.sdks.python","Python SDK","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fpieces-os-client-sdk-for-python",{"key":541,"label":542,"href":543},"github.sdks.typescript","TypeScript SDK","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fpieces-os-client-sdk-for-typescript",{"key":545,"label":546,"href":547},"github.sdks.dart","Dart SDK","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fpieces-os-client-sdk-for-dart",{"key":549,"label":550,"href":551},"github.sdks.kotlin","Kotlin SDK","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fpieces-os-client-sdk-for-kotlin",{"key":553,"label":554,"href":555},"github.plugins.obsidian","Obsidian plugin repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fobsidian-pieces",{"key":557,"label":558,"href":255},"github.plugins.jupyterlab","JupyterLab plugin repository",{"key":560,"label":561,"href":562},"github.plugins.sublime","Sublime plugin repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fplugin_sublime",{"key":564,"label":565,"href":566},"github.plugins.neovim","Neovim plugin repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fplugin_neovim",{"key":568,"label":569,"href":570},"github.cliAgent","CLI agent repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fcli-agent",{"key":572,"label":573,"href":574},"github.mcpDart","MCP Dart repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fmcp_dart",{"key":576,"label":577,"href":578},"github.awesomePieces","Awesome Pieces repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fawesome-pieces",{"key":580,"label":581,"href":66},"legal.privacyPolicy","Privacy policy",{"key":583,"label":584,"href":69},"legal.refundPolicy","Refund policy",{"key":586,"label":587,"href":72},"legal.terms","Terms",{"key":589,"label":590,"href":591},"legal.security","Legal security","https:\u002F\u002Fpieces.app\u002Flegal\u002Fsecurity",{"key":593,"label":594,"href":511},"videos.youtubeChannel","YouTube channel",{"key":596,"label":597,"href":598},"videos.gettingStartedDesktop","Getting started desktop video","https:\u002F\u002Fyoutu.be\u002FdUr1lRM_TYk",{"key":600,"label":601,"href":602},"videos.snippetDiscoveryxR","Snippet discovery video","https:\u002F\u002Fyoutu.be\u002FG6vb1USw-30",{"key":604,"label":605,"href":606},"sales.bookACall","Book a sales call","https:\u002F\u002Fcalendar.app.google\u002FWVUDtUfNy5Vst3sH7",{"key":608,"label":609,"href":610},"sales.enterprise","Enterprise form","https:\u002F\u002Fgetpieces.typeform.com\u002Fto\u002FaVQFTvpE",{"key":612,"label":613,"href":527},"sales.feedback","Feedback discussions",{"key":615,"label":616,"href":617},"sales.earlyAccess","Early access form","https:\u002F\u002Fgetpieces.typeform.com\u002Fearlyaccess",{"key":619,"label":620,"href":621},"sales.supportEmail","Support email","mailto:support@pieces.app",{"key":623,"label":624,"href":19},"routes.home","Home route",{"key":626,"label":627,"href":56},"routes.about","About route",{"key":629,"label":630,"href":12},"routes.downloads","Downloads route",{"key":632,"label":633,"href":634},"routes.thanks","Post-install thanks route","\u002Finstall\u002Fthanks",{"key":636,"label":637,"href":638},"routes.pricing","Pricing route","\u002Fpricing",{"key":640,"label":641,"href":642},"cta.freeTrial","Start free trial CTA (Pieces Pro) — used by \u002Fcampaigns\u002F* landing pages","https:\u002F\u002Fcampaigns.pieces.app\u002F",{"key":644,"label":645,"href":22},"routes.enterprise","Enterprise route",{"key":647,"label":648,"href":62},"routes.contact","Contact route",{"key":650,"label":651,"href":59},"routes.updates","Updates route",{"key":653,"label":654,"href":655},"routes.migrationError","Migration error route","\u002Fmigration\u002Ferror",{"key":657,"label":658,"href":659},"routes.authenticated","Post-login authenticated route","\u002Fauth\u002Fsigned-in",{"key":661,"label":662,"href":663},"routes.signed-out","Signed out route","\u002Fauth\u002Fsigned-out",{"key":665,"label":666,"href":667},"routes.authentication-error","Authentication error route","\u002Fauth\u002Ferror",{},"data\u002Fshared\u002Furls","2AvfSWI6bZACH5Kr1ZS3txMLjteRjCjbDR_ul1uRZ9Q",{"id":672,"title":673,"author":674,"authorPhoto":675,"authorPhotoAlt":676,"authorSlug":677,"body":678,"buttonText":1177,"buttonUrl":1178,"category":1179,"date":1180,"description":1181,"draft":1182,"editorsPick":1182,"extension":1183,"featured":1182,"image":1184,"imageAlt":676,"meta":1185,"navigation":32,"ogImage":676,"ogImageAlt":676,"path":1186,"seo":1187,"stem":1188,"tags":676,"__hash__":1189},"blog\u002Fblog\u002Fentity-resolution-with-data-flow.md","Acceptable and fast user entity resolution using dataflow","Hiro Tamada","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Fentity-resolution-with-data-flow\u002Fauthor.jpg",null,"hiro-tamada",{"type":679,"value":680,"toc":1165},"minimark",[681,685,688,693,696,700,703,706,709,713,723,726,729,732,735,738,741,749,752,755,758,761,764,767,784,787,794,810,817,835,842,864,867,882,892,895,945,948,954,960,966,969,972,975,989,992,997,1000,1003,1006,1010,1013,1124,1130,1134,1137,1140,1143,1149,1152,1159,1162],[682,683,684],"p",{},"Entity resolution is a well-established and prevalent challenge in software engineering. Many organizations face the issue of having user-related data dispersed across various databases and systems.",[682,686,687],{},"This fragmentation can lead to significant difficulties when analyzing and correlating user demographics and activities across different data sources, particularly in analytics. Entity resolution consolidates and groups information about the same users.",[689,690,692],"h2",{"id":691},"what-is-entity-resolution","What is entity resolution?",[682,694,695],{},"Entity Resolution (ER) is the process of identifying and merging records that refer to the same real-world entities across different data sources. Generally speaking, it helps to create a unified and accurate view of data by linking data points in relational data, eliminating duplicates, and improving overall data quality.",[689,697,699],{"id":698},"what-is-the-difference-between-record-linkage-and-entity-resolution","What is the difference between record linkage and entity resolution?",[682,701,702],{},"Entity resolution is a form of graph traversal of scattered user information.",[682,704,705],{},"For example, if a user has two login accounts with different emails but with the same home address these accounts are highly likely to be connected. In other words, these accounts (nodes) can be traversed through address relationships (nodes).",[682,707,708],{},"In our situation, we have the same users having the same exact emails or IP addresses but different osId since osId can be recreated after reinstallation.  The purpose of this entity resolution is to traverse through these scattered OSIds by PIIs and connect them.",[689,710,712],{"id":711},"why-is-entity-resolution-useful","Why is entity resolution useful?",[682,714,715,716,722],{},"In a startup, it is incredibly important for us to accurately track our users' behavior, helping us understand what is working and what isn’t when it comes to product releases, growth activities, and the general software lifecycle. When I joined ",[717,718,8],"a",{"href":719,"rel":720},"https:\u002F\u002Fpieces.app\u002F",[721],"nofollow",", I encountered this issue firsthand.",[682,724,725],{},"One of my initial projects involved accurately capturing user activity events. At that time, the existing approach for user activity analytics involved sending events to the analytics platform via Segment, followed by manual filtering on the analytics side.",[682,727,728],{},"Each event was tagged with a UUID generated by our software, which was primarily used to track activity on a per-user basis.",[682,730,731],{},"However, this method presented several challenges:",[682,733,734],{},"Firstly, the event schema was not standardized, as Segment accepts virtually any JSON format. This resulted in multiple instances within the client codebase where Segment events were being sent with varying schemas.",[682,736,737],{},"Secondly, when a user uninstalls and reinstalls our software, a new UUID is generated, causing events associated with the new UUID to be mistakenly counted as activity from a new user.",[682,739,740],{},"While the first issue could be addressed by standardizing the schema and client-side code, we still faced the challenge of analyzing events that had already been sent. This required developing a strategy to retrospectively resolve and consolidate user data to ensure accurate analytics.",[682,742,743,744,748],{},"We selected Google Cloud Dataflow to manage and process over three years of user activity event data. This dataset contains ",[745,746,747],"strong",{},"more than 200 million events",", with the volume set to grow significantly in the future.",[682,750,751],{},"Since our tech stack is heavily based on Google Cloud services, Dataflow was a natural fit, allowing us to build a highly scalable pipeline to aggregate and transform raw event data sourced from Mixpanel.",[682,753,754],{},"In the initial phase of the project, our primary goal was to identify each unique user by their universally unique identifier (UUID), which we refer to as \"osId\" (we’ll use this term going forward).",[682,756,757],{},"Our user activity data resided exclusively on the analytics platform, so to enable Dataflow to perform efficient, scalable batch processing, we needed to transfer this data to Google Cloud Storage (GCS).",[682,759,760],{},"To achieve this, we created a scheduled job on Cloud Run, which retrieves data files from the analytics platform and stores them in GCS (We’ll cover the specifics of this technique in another blog post, but for now, assume that all raw JSON events are available in GCS.)",[682,762,763],{},"As mentioned, osIds could appear in various parts of the raw JSON data and are not marked with consistent property names.",[682,765,766],{},"To accurately locate the correct osIds, we developed a set of assumptions:",[768,769,770,779],"ol",{},[771,772,773,774,778],"li",{},"If the UUID appears multiple times across different events historically, it is more likely to be an ",[775,776,777],"code",{},"os_id",".",[771,780,781,782,778],{},"If the UUID has appeared historically with the key or parent key as \"os,\" it is also more likely to be an ",[775,783,777],{},[682,785,786],{},"Based on these assumptions, we created the following strategy to find the osId:",[768,788,789],{},[771,790,791],{},[745,792,793],{},"Identify Potential UUIDs in Event JSONs:",[795,796,797,800,803],"ul",{},[771,798,799],{},"For each event JSON, scan for all strings that match a UUID pattern using regex.",[771,801,802],{},"For each matching string, check if the \"os\" key appears either as a direct or parent key.",[771,804,805,806,809],{},"Construct an entity of ",[775,807,808],{},"PotentialUUID(uuid=..., isOsPath=...)"," for each matching UUID.",[768,811,812],{},[771,813,814],{},[745,815,816],{},"Aggregate Historical UUID Data:",[795,818,819,826,829],{},[771,820,821,822,825],{},"Aggregate all ",[775,823,824],{},"PotentialUUID"," entities across historical event JSONs.",[771,827,828],{},"Count the number of historical occurrences for each UUID and track whether it has ever appeared with an \"os\" key.",[771,830,831,832,778],{},"After aggregation, you will have a ",[775,833,834],{},"PotentialUUID(uuid=..., numberOfHistoricalOccurrences=..., everAppearedAsOs=...)",[768,836,837],{},[771,838,839],{},[745,840,841],{},"Attach Most Likely os_id to Each Event:",[795,843,844,847,850,861],{},[771,845,846],{},"For each user activity event, extract all regex-matching UUIDs.",[771,848,849],{},"Join these UUIDs with the aggregated PotentialUUID data.",[771,851,852,853],{},"Rank the PotentialUUID candidates by:",[795,854,855,858],{},[771,856,857],{},"Whether they have everAppearedAsOs.",[771,859,860],{},"Their numberOfHistoricalOccurrences.",[771,862,863],{},"Attach the highest-ranked PotentialUUID as the os_id to the event.",[682,865,866],{},"We chose Scala along with Scio, a library that enables Apache Beam to run on Google Cloud Dataflow, to build our data processing pipeline. This combination is well-suited for easily processing large datasets and allows for efficient parallel computation.",[682,868,869,870,873,874,877,878,881],{},"The code snippet below shows how we implemented a custom aggregator to manage and aggregate potential ",[775,871,872],{},"osId"," data across various attributes. The ",[775,875,876],{},"PotentialOsIdAggregator"," class extends the ",[775,879,880],{},"Aggregator"," trait, defining the logic for preparing, merging, and presenting aggregated data.",[883,884,889],"pre",{"className":885,"code":887,"language":888},[886],"language-text","class PotentialOsIdAggregator extends Aggregator[PotentialOsId, PotentialOsId, PotentialOsId] {\n\n  \u002F\u002F Defines a custom semigroup for merging two PotentialOsId instances\n  implicit val osIdSemigroup: Semigroup[PotentialOsId] = (l: PotentialOsId, r: PotentialOsId) => (l + r)\n\n  \u002F\u002F Specifies how to prepare input data for aggregation\n  override def prepare(input: PotentialOsId): PotentialOsId = input\n\n  \u002F\u002F Provides the defined semigroup for combining inputs\n  override def semigroup: Semigroup[PotentialOsId] = osIdSemigroup\n\n  \u002F\u002F Finalizes and presents the aggregated result\n  override def present(reduction: PotentialOsId): PotentialOsId = reduction\n}\n\n\u002F\u002F Case class representing potential osId details with fields for emails, IP addresses, etc.\ncase class PotentialOsId(potentialOsId: String,\n                         emails: Set[String],\n                         ipAddresses: Set[String],\n                         userNames: Set[String],\n                         numOccurrences: Int = 1,\n                         minTimestamp: Long = 0,\n                         isOsUser: Boolean) {\n\n  \u002F\u002F Merges two PotentialOsId instances by combining fields\n  def +(other: PotentialOsId): PotentialOsId = {\n    PotentialOsId(\n      potentialOsId = this.potentialOsId,\n      emails = this.emails ++ other.emails,\n      ipAddresses = this.ipAddresses ++ other.ipAddresses,\n      userNames = this.userNames ++ other.userNames,\n      numOccurrences = this.numOccurrences + other.numOccurrences,\n      minTimestamp = Math.min(this.minTimestamp, other.minTimestamp),\n      isOsUser = this.isOsUser || other.isOsUser\n    )\n  }\n}\n\n\u002F\u002F Aggregates osId data by grouping by potentialOsId key\ndef aggregatePotentialOsIdStats(): SCollection[PotentialOsId] = potentialOsIds.keyBy(\n  _.potentialOsId\n).aggregateByKey(\n  new PotentialOsIdAggregator\n).values\n","text",[775,890,887],{"__ignoreMap":891},"",[682,893,894],{},"Here’s a breakdown of each part:",[768,896,897,913,925],{},[771,898,899,901,902,905,906,909,910,912],{},[745,900,876],{},": This class aggregates ",[775,903,904],{},"PotentialOsId"," objects, leveraging a custom-defined ",[775,907,908],{},"Semigroup"," to specify how two ",[775,911,904],{}," instances should be combined. This process includes merging attributes like emails, IP addresses, and usernames, along with maintaining a count of occurrences and a minimum timestamp.",[771,914,915,918,919,921,922,924],{},[745,916,917],{},"PotentialOsId Case Class",": This case class models each potential ",[775,920,872],{}," and its associated metadata. The + method defines the logic for merging two instances of ",[775,923,904],{},", which the aggregator uses to incrementally build the combined results.",[771,926,927,930,931,934,935,937,938,941,942,944],{},[745,928,929],{},"aggregatePotentialOsIdStats Function",": This function groups the ",[775,932,933],{},"potentialOsId"," data by unique ",[775,936,872],{}," values and then applies the custom aggregator to compute aggregate statistics. The result is an ",[775,939,940],{},"SCollection"," of combined ",[775,943,904],{}," objects, which can be further processed or stored.",[682,946,947],{},"This setup is highly efficient, as Scio allows us to parallelize data processing in Dataflow, scaling seamlessly to accommodate our large dataset.",[682,949,950,951,953],{},"To give a clear view of our aggregation process, we also capture users' personally identifiable information (PII), such as emails and IP addresses, while aggregating ",[775,952,904],{}," data. This information is essential for grouping related identifiers, helping us to build a cohesive view of user activities across events.",[682,955,956,957,959],{},"The diagram below visually represents the aggregation process, showcasing how raw event data is transformed as we consolidate various attributes into a single ",[775,958,904],{}," record.",[682,961,962],{},[963,964],"img",{"alt":891,"src":965},"https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Fentity-resolution-with-data-flow\u002Fimg-001.png",[682,967,968],{},"With our historical event data now containing accurate osId values and corresponding PotentialOsId objects that include associated personally identifiable information (PII), we’re ready to address the next challenge: users who receive a different osId upon reinstalling the app.",[682,970,971],{},"To tackle this, we use the data we've gathered on UUIDs, usernames, and emails to establish mappings between these identifiers, creating a network of relationships that allows us to resolve user entities even when UUIDs differ.",[682,973,974],{},"This solution involves building a graph where:",[795,976,977,983],{},[771,978,979,982],{},[745,980,981],{},"Nodes"," represent UUIDs, usernames, and emails.",[771,984,985,988],{},[745,986,987],{},"Edges"," connect nodes that share a relationship, like a UUID linked to an email or username based on historical data.",[682,990,991],{},"For instance, two UUIDs may be connected if they share the same email address or username, indicating they likely belong to the same user. By finding connected components in this graph, we can cluster related UUIDs and resolve users across different UUIDs.",[993,994,996],"h3",{"id":995},"simplifying-the-graph-traversal-in-dataflow","Simplifying the graph traversal in dataflow",[682,998,999],{},"Typically, graph traversal is computationally expensive, especially if it requires exploring all possible node connections in an infinite loop.",[682,1001,1002],{},"However, Google Cloud Dataflow requires a Directed Acyclic Graph (DAG) structure for processing, which disallows any looping or recursive operations.",[682,1004,1005],{},"Instead of an exhaustive traversal, we made a practical assumption: most connected osId components share PII and can be linked within two or three degrees of connection. This limited traversal is sufficient to find most connected components in our data.",[689,1007,1009],{"id":1008},"steps-for-dataflow-aggregation","Steps for dataflow aggregation",[682,1011,1012],{},"To implement this solution in Dataflow, we followed these steps:",[768,1014,1015,1054,1072,1096,1114],{},[771,1016,1017,1020,1021,1020,1023,1026,1027,1029,1030,1033,1034,1037,1038,1041,1042],{},[745,1018,1019],{},"Flat Mapping"," ",[775,1022,904],{},[745,1024,1025],{},"and PII",": For each ",[775,1028,872],{},", we create pairs with each PII element. For instance, if ",[775,1031,1032],{},"osId1"," is associated with emails ",[775,1035,1036],{},"[email1@email.com, email2@email.com]"," and usernames ",[775,1039,1040],{},"[userName1, userName2]",", we generate pairs like:",[795,1043,1044,1049],{},[771,1045,1046],{},[775,1047,1048],{},"(osId1, email1@email.com), (osId1, email2@email.com)",[771,1050,1051],{},[775,1052,1053],{},"(osId1, userName1), (osId1, userName2)",[771,1055,1056,1059,1060],{},[745,1057,1058],{},"Aggregating by PII",": Next, we aggregate all pairs by the PII element on the right side. This yields mappings such as:",[795,1061,1062,1067],{},[771,1063,1064],{},[775,1065,1066],{},"(email1@email.com, [osId1, osId2…])",[771,1068,1069],{},[775,1070,1071],{},"(userName1, [osId1, osId2…])",[771,1073,1074,1020,1077,1080,1081,1083,1084,1087,1088],{},[745,1075,1076],{},"Generating Pairs of",[775,1078,1079],{},"osIds",": For each list of ",[775,1082,1079],{}," associated with a particular PII element, we generate all possible combinations. For instance, if a username is linked to ",[775,1085,1086],{},"[osId1, osId2, osId3]",", we create pairs like:",[795,1089,1090],{},[771,1091,1092,1095],{},[775,1093,1094],{},"[osId1, osId2], [osId2, osId1], [osId2, osId3]",", etc.",[771,1097,1098,1020,1101,1103,1104,1106,1107],{},[745,1099,1100],{},"Aggregating by",[775,1102,872],{},": We then aggregate these combinations by ",[775,1105,872],{}," on the left side, ultimately yielding clusters such as:",[795,1108,1109],{},[771,1110,1111],{},[775,1112,1113],{},"(osId1, [osId1, osId2, osId3])",[771,1115,1116,1020,1119,1121,1122,778],{},[745,1117,1118],{},"Extracting Unique",[775,1120,1079],{},": Finally, we extract each cluster's unique set of ",[775,1123,1079],{},[682,1125,1126,1127,1129],{},"While the current implementation of this method doesn’t account for every possible method, it effectively identifies the majority of related ",[775,1128,872],{}," components, creating a robust entity resolution framework.",[993,1131,1133],{"id":1132},"managing-costs-and-estimating-performance","Managing costs and estimating performance",[682,1135,1136],{},"This Dataflow job is both efficient and cost-effective. Processing all historical data takes around 30 minutes and costs approximately $3, making it an excellent solution for our use case.",[682,1138,1139],{},"As a result, we can now more accurately capture Pieces user activity events, allowing us to understand how our product is being used and make accurate assumptions and predictions about user behavior.",[682,1141,1142],{},"I initially dumped the existing user activity data into a data warehouse (specifically BigQuery) to analyze the data.",[682,1144,1145,1146,778],{},"I spent significant time querying the data to come up with a solution or an algorithm to find connected ",[775,1147,1148],{},"OSIds",[682,1150,1151],{},"Throughout this process, I had to jump between the BigQuery console on my browser and the actual implementation with Scala on IntelliJ.",[682,1153,1154,1158],{},[717,1155,8],{"href":1156,"rel":1157},"https:\u002F\u002Fpieces.app\u002Fuse-cases\u002Fsoftware-engineers",[721]," WPE helped me remember the queries I created and translated in Scala. For example, I was able to ask “Do you remember the query to connect osIds through emails?",[682,1160,1161],{},"If so, could you translate it into scio\u002Fscala?”.",[682,1163,1164],{},"Pieces gave me almost perfect answers and saved a lot of time.",{"title":891,"searchDepth":1166,"depth":1166,"links":1167},2,[1168,1169,1170,1174],{"id":691,"depth":1166,"text":692},{"id":698,"depth":1166,"text":699},{"id":711,"depth":1166,"text":712,"children":1171},[1172],{"id":995,"depth":1173,"text":996},3,{"id":1008,"depth":1166,"text":1009,"children":1175},[1176],{"id":1132,"depth":1173,"text":1133},"Download Pieces","https:\u002F\u002Fdocs.pieces.app\u002Finstallation-getting-started\u002Fwhat-am-i-installing","Software Development","2024-12-06T00:00:00.000Z","Learn what entity resolution is and how to implement it effectively using dataflow. Check out insights from our developers and practical steps to help you improve data quality.",false,"md","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Fentity-resolution-with-data-flow\u002Fhero.png",{},"\u002Fblog\u002Fentity-resolution-with-data-flow",{"title":673,"description":1181},"blog\u002Fentity-resolution-with-data-flow","sJkSDHhxyBT4ttKhvRDxc2Xufqqqk_gZRfCTIwEpN74",{"id":1191,"title":674,"body":1192,"description":891,"draft":1182,"extension":1183,"meta":1196,"navigation":32,"path":1197,"photo":1198,"photoAlt":676,"seo":1199,"stem":1200,"__hash__":1201},"authors\u002Fauthors\u002Fhiro-tamada.md",{"type":679,"value":1193,"toc":1194},[],{"title":891,"searchDepth":1166,"depth":1166,"links":1195},[],{},"\u002Fauthors\u002Fhiro-tamada","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fauthors\u002Fhiro-tamada.png",{"title":674,"description":891},"authors\u002Fhiro-tamada","QRukcIrAEfzjHun794g_GF4g0d51xC7p66Ow8hu5VsU",{"left":1203,"top":1203,"width":1204,"height":1204,"rotate":1203,"vFlip":1182,"hFlip":1182,"body":1205},0,24,"\u003Cpath fill=\"currentColor\" d=\"m7.825 13l4.9 4.9q.3.3.288.7t-.313.7q-.3.275-.7.288t-.7-.288l-6.6-6.6q-.15-.15-.213-.325T4.426 12t.063-.375t.212-.325l6.6-6.6q.275-.275.688-.275t.712.275q.3.3.3.713t-.3.712L7.825 11H19q.425 0 .713.288T20 12t-.288.713T19 13z\"\u002F>"]