This is an automated email from the ASF dual-hosted git repository.

jeffreyh pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris-website.git


The following commit(s) were added to refs/heads/master by this push:
     new 97acac53344 [Fix]: Redirect some links (#2971)
97acac53344 is described below

commit 97acac53344a07789433b25bfcb83416f021a471
Author: yangon <[email protected]>
AuthorDate: Tue Oct 14 15:46:09 2025 +0800

    [Fix]: Redirect some links (#2971)
---
 docusaurus.config.js                |   9 +-
 scripts/extractExternalLinks.js     |  57 +++++++
 src/theme/BlogPostItem/blog.data.ts | 288 ++++++++++++++++++++++++++++++++++++
 src/theme/BlogPostItem/index.tsx    |  15 +-
 4 files changed, 362 insertions(+), 7 deletions(-)

diff --git a/docusaurus.config.js b/docusaurus.config.js
index 0a2a9f67f1a..70238b16bf2 100644
--- a/docusaurus.config.js
+++ b/docusaurus.config.js
@@ -122,22 +122,19 @@ const config = {
                     {
                         from: '/docs/dev/get-starting/',
                         to: 
`/docs/${DEFAULT_VERSION}/gettingStarted/quick-start`,
-                    },
+                    }
                 ],
                 createRedirects(existingPath) {
-                    if 
(existingPath.includes('/gettingStarted/what-is-apache-doris')) {
+                    if 
(existingPath.includes('/gettingStarted/what-is-apache-doris') || 
existingPath.startsWith('/docs/3.x/')) {
                         // Redirect from /gettingStarted/what-is-new to 
/gettingStarted/what-is-apache-doris
                         return [
                             existingPath.replace(
                                 '/gettingStarted/what-is-apache-doris',
                                 '/gettingStarted/what-is-new',
                             ),
+                            existingPath.replace('/docs/3.x/', '/docs/'), 
existingPath.replace('/docs/3.x/', '/docs/3.0/')
                         ];
                     }
-                    if (existingPath.startsWith('/docs/3.x/')) {
-                        return [existingPath.replace('/docs/3.x/', '/docs/'), 
existingPath.replace('/docs/3.x/', '/docs/3.0/')];
-                    }
-
                     return undefined; // Return a falsy value: no redirect 
created
                 },
             },
diff --git a/scripts/extractExternalLinks.js b/scripts/extractExternalLinks.js
new file mode 100644
index 00000000000..446577f99bc
--- /dev/null
+++ b/scripts/extractExternalLinks.js
@@ -0,0 +1,57 @@
+const fs = require('fs');
+const path = require('path');
+
+// Traverse all md files in the directory
+function getAllMarkdownFiles(dir) {
+  let results = [];
+  const files = fs.readdirSync(dir);
+
+  for (const file of files) {
+    const filePath = path.join(dir, file);
+    const stat = fs.statSync(filePath);
+
+    if (stat.isDirectory()) {
+      results = results.concat(getAllMarkdownFiles(filePath));
+    } else if (file.endsWith('.md')) {
+      results.push(filePath);
+    }
+  }
+
+  return results;
+}
+
+// Extract the externalLink of frontMatter
+function extractExternalLink(filePath) {
+  const content = fs.readFileSync(filePath, 'utf-8');
+  const frontMatterMatch = content.match(/^---\s*([\s\S]*?)\s*---/);
+
+  if (!frontMatterMatch) return null;
+
+  const frontMatter = frontMatterMatch[1];
+
+  // Try to resolve externalLink
+  const linkMatch = 
frontMatter.match(/['"]externalLink['"]\s*:\s*['"]([^'"]+)['"]/);
+
+  if (!linkMatch) return null;
+
+  return linkMatch[1];
+}
+
+function main() {
+  const blogDir = path.join(__dirname, '../blog');
+  const mdFiles = getAllMarkdownFiles(blogDir);
+
+  const result = [];
+
+  for (const file of mdFiles) {
+    const externalLink = extractExternalLink(file);
+    if (externalLink) {
+      const relativePath = '/blog/' + path.basename(file, '.md');
+      result.push({ path: relativePath, externalLink });
+    }
+  }
+
+  console.log(JSON.stringify(result, null, 2));
+}
+
+main();
diff --git a/src/theme/BlogPostItem/blog.data.ts 
b/src/theme/BlogPostItem/blog.data.ts
new file mode 100644
index 00000000000..98690aa3628
--- /dev/null
+++ b/src/theme/BlogPostItem/blog.data.ts
@@ -0,0 +1,288 @@
+export const BLOG_RELATED_EXTERNAL_LINK = [
+    {
+        path: '/blog/1-billion-json-records-1-second-query-response',
+        externalLink: 'https://www.velodb.io/blog/1422',
+    },
+    {
+        path: 
'/blog/Auto-Synchronization-of-an-Entire-MySQL-Database-for-Data-Analysis',
+        externalLink: 'https://www.velodb.io/blog/135',
+    },
+    {
+        path: 
'/blog/Choosing-an-OLAP-Engine-for-Financial-Risk-Management-What-to-Consider',
+        externalLink: 'https://www.velodb.io/blog/136',
+    },
+    {
+        path: 
'/blog/Database-in-Fintech-How-to-Support-ten-thousand-Dashboards-Without-Causing-a-Mess',
+        externalLink: 'https://www.velodb.io/blog/133',
+    },
+    {
+        path: 
'/blog/Log-Analysis-How-to-Digest-15-Billion-Logs-Per-Day-and-Keep-Big-Queries-Within-1-Second',
+        externalLink: 'https://www.velodb.io/blog/137',
+    },
+    {
+        path: 
'/blog/Replacing-Apache-Hive-Elasticsearch-and-PostgreSQL-with-Apache-Doris',
+        externalLink: 'https://www.velodb.io/blog/1372',
+    },
+    {
+        path: '/blog/Tencent-LLM',
+        externalLink: 'https://www.velodb.io/blog/131',
+    },
+    {
+        path: 
'/blog/a-fast-secure-high-available-real-time-data-warehouse-based-on-apache-doris',
+        externalLink: 'https://www.velodb.io/blog/155',
+    },
+    {
+        path: 
'/blog/a-financial-anti-fraud-solution-based-on-the-apache-doris-data-warehouse',
+        externalLink: 'https://www.velodb.io/blog/165',
+    },
+    {
+        path: 
'/blog/ai-unicorn-minimax-from-loki-and-built-a-pb-scale-logging-system-with-doris',
+        externalLink: 'https://www.velodb.io/blog/883',
+    },
+    {
+        path: '/blog/apache-doris-and-deepseek-community-voice',
+        externalLink:
+            
'https://medium.com/%40xudarren1023/apache-doris-and-deepseek-redefining-intelligent-data-analytics-2b6b778e1034',
+    },
+    {
+        path: 
'/blog/apache-doris-and-iceberg-building-hyperscale-data-lakehouse',
+        externalLink: 'https://www.velodb.io/blog/1450',
+    },
+    {
+        path: 
'/blog/apache-doris-empowered-5G-fully-connected-factory-with-a-unified-real-time-data-platform',
+        externalLink: 'https://www.velodb.io/blog/1446',
+    },
+    {
+        path: 
'/blog/apache-doris-for-log-and-time-series-data-analysis-in-netease',
+        externalLink: 'https://www.velodb.io/blog/437',
+    },
+    {
+        path: 
'/blog/apache-doris-speeds-up-data-reporting-tagging-and-data-lake-analytics',
+        externalLink: 'https://www.velodb.io/blog/152',
+    },
+    {
+        path: '/blog/apache-doris-the-data-lakehouse-evolution',
+        externalLink: 'https://www.velodb.io/blog/1411',
+    },
+    {
+        path: '/blog/apache-doris-vs-rockset',
+        externalLink: 'https://www.velodb.io/blog/567',
+    },
+    {
+        path: 
'/blog/arrow-flight-sql-in-apache-doris-for-10x-faster-data-transfer',
+        externalLink: 'https://www.velodb.io/blog/295',
+    },
+    {
+        path: '/blog/auto-increment-columns-in-databases',
+        externalLink: 'https://www.velodb.io/blog/252',
+    },
+    {
+        path: '/blog/auto-partition-in-apache-doris',
+        externalLink: 'https://www.velodb.io/blog/882',
+    },
+    {
+        path: '/blog/breaking-down-data-silos-with-an-apache-doris-based-cdp',
+        externalLink: 'https://www.velodb.io/blog/172',
+    },
+    {
+        path: '/blog/building-real-time-lakehouse-with-apache-doris',
+        externalLink: 'https://www.velodb.io/blog/1428',
+    },
+    {
+        path: '/blog/coffeebench-olap-showdown-part1-250829',
+        externalLink: 'https://www.velodb.io/blog/1463',
+    },
+    {
+        path: '/blog/coffeebench-part2-250917',
+        externalLink: 'https://www.velodb.io/blog/1504',
+    },
+    {
+        path: 
'/blog/community-voice-2025-how-do-you-choose-between-doris-and-clickhouse',
+        externalLink:
+            
'https://medium.com/@ith321.vip/its-2025-how-do-you-choose-between-doris-and-clickhouse-7d98456d9199',
+    },
+    {
+        path: 
'/blog/community-voice-cut-costs-and-boost-efficiency-how-doriss-unified-lakehouse-breaks-down-data-silos',
+        externalLink:
+            
'https://medium.com/@hhj19075/cut-costs-and-boost-efficiency-how-doriss-unified-lakehouse-breaks-down-data-silos-bfb1c9cd079a',
+    },
+    {
+        path: 
'/blog/community-voice-doris-breaking-down-the-barriers-of-sql-dialects-and-building-a-unified-data-query-ecosystem',
+        externalLink:
+            
'https://dev.to/darren_xu/doris-breaking-down-the-barriers-of-sql-dialects-and-building-a-unified-data-query-ecosystem-37k1',
+    },
+    {
+        path: '/blog/community-voice-doris-lakehouse-integration',
+        externalLink: 'https://dzone.com/articles/doris-lakehouse-integration',
+    },
+    {
+        path: 
'/blog/community-voice-lakehouse-manus-mcp-lets-talk-about-lakehouse',
+        externalLink: 
'https://dzone.com/articles/lakehouse-manus-mcp-lets-talk-about-lakehouse',
+    },
+    {
+        path: 
'/blog/community-voice-lakehouse-starting-with-apache-doris-s3-tables',
+        externalLink:
+            
'https://medium.com/@morningman.cmy/lakehousewbd-1-starting-with-apache-doris-s3-tables-10c98ae39fe1',
+    },
+    {
+        path: '/blog/community-voice-when-doris-meets-iceberg',
+        externalLink: 'https://dzone.com/articles/when-doris-meets-iceberg',
+    },
+    {
+        path: '/blog/cross-cluster-replication-for-read-write',
+        externalLink: 'https://www.velodb.io/blog/339',
+    },
+    {
+        path: 
'/blog/data-analysis-for-live-streaming-what-happens-in-real-time-is-analyzed-in-real-time',
+        externalLink: 'https://www.velodb.io/blog/139',
+    },
+    {
+        path: '/blog/data-pruning-250908',
+        externalLink: 'https://www.velodb.io/blog/1489',
+    },
+    {
+        path: '/blog/data-trait-250905',
+        externalLink: 'https://www.velodb.io/blog/1488',
+    },
+    {
+        path: '/blog/doris-compute-storage-decoupled',
+        externalLink: 'https://www.velodb.io/blog/1384',
+    },
+    {
+        path: '/blog/doris-introduction-community-voice',
+        externalLink: 'https://www.baeldung.com/sql/apache-doris-tutorial',
+    },
+    {
+        path: '/blog/elasticsearch-vs-apache-doris-community-voice',
+        externalLink:
+            
'https://www.linkedin.com/posts/rahul-kolluri-352447191_rethinking-elasticsearch-for-analytics-activity-7333804955700473859-2-e4?utm_source=share&utm_medium=member_desktop&rcm=ACoAACoH8OcBYW4CFSr632eidBaUEb5u1O2r30o',
+    },
+    {
+        path: '/blog/emqx-apache-doris-ecosystem-for-iot-analytics',
+        externalLink: '1-billion-json-records-1-second-query-response',
+    },
+    {
+        path: '/blog/evolution-of-the-apache-doris-execution-engine',
+        externalLink: 'https://www.velodb.io/blog/573',
+    },
+    {
+        path: '/blog/from-clickhouse-to-doris-trillion-log-scale-analytics',
+        externalLink: 'https://www.velodb.io/blog/1429',
+    },
+    {
+        path: '/blog/from-elasticsearch-to-doris-boosting-queries-by-56x',
+        externalLink: 'https://www.velodb.io/blog/1427',
+    },
+    {
+        path: 
'/blog/from-presto-trino-clickhouse-and-hive-to-apache-doris-sql-convertor-for-easy-migration',
+        externalLink: 'https://www.velodb.io/blog/377',
+    },
+    {
+        path: 
'/blog/from-snowflake-to-apache-doris-real-time-analytics-with-80-percentage-cost-savings',
+        externalLink: 'https://www.velodb.io/blog/1435',
+    },
+    {
+        path: 
'/blog/how-big-data-is-saving-lives-in-real-time-iov-data-analytics-helps-prevent-accidents',
+        externalLink: 'https://www.velodb.io/blog/141',
+    },
+    {
+        path: 
'/blog/introduction-to-apache-doris-a-next-generation-real-time-data-warehouse',
+        externalLink: 'https://www.velodb.io/blog/127',
+    },
+    {
+        path: 
'/blog/inverted-index-accelerates-text-searches-by-40-time-apache-doris',
+        externalLink: 'https://www.velodb.io/blog/163',
+    },
+    {
+        path: '/blog/job-scheduler-for-task-automation',
+        externalLink: 'https://www.velodb.io/blog/574',
+    },
+    {
+        path: 
'/blog/kwai-replace-clickhouse-with-apache-doris-for-unified-lakehouse',
+        externalLink: 'https://www.velodb.io/blog/1432',
+    },
+    {
+        path: 
'/blog/leading-ai-company-revamped-observability-with-apache-doris',
+        externalLink: 'https://www.velodb.io/blog/1434',
+    },
+    {
+        path: 
'/blog/less-components-higher-performance-apache-doris-instead-of-clickhouse-mysql-presto-and-hbase',
+        externalLink: 'https://www.velodb.io/blog/140',
+    },
+    {
+        path: '/blog/linkedcare',
+        externalLink: 'https://www.velodb.io/blog/1373',
+    },
+    {
+        path: '/blog/log-analysis-elasticsearch-vs-apache-doris',
+        externalLink: 'https://www.velodb.io/blog/132',
+    },
+    {
+        path: '/blog/migrate-lakehouse-from-bigquery-to-doris',
+        externalLink: 'https://www.velodb.io/blog/689',
+    },
+    {
+        path: '/blog/migrating-from-clickhouse-to-apache-doris-what-happened',
+        externalLink: 'https://www.velodb.io/blog/138',
+    },
+    {
+        path: '/blog/multi-tenant-workload-isolation-in-apache-doris',
+        externalLink: 'https://www.velodb.io/blog/403',
+    },
+    {
+        path: 
'/blog/real-time-analytical-data-platform-for-the-agentic-ai-era',
+        externalLink: 'https://www.velodb.io/blog/1444',
+    },
+    {
+        path: 
'/blog/real-time-data-analytics-at-scale-integrating-apache-flink-and-doris',
+        externalLink: 'https://www.velodb.io/blog/1453',
+    },
+    {
+        path: 
'/blog/real-time-lakehouse-in-cainiao-large-scale-business-scenarios',
+        externalLink: 'https://www.velodb.io/blog/1454',
+    },
+    {
+        path: '/blog/real-time-update-deep-dive',
+        externalLink: 'https://www.velodb.io/blog/1431',
+    },
+    {
+        path: '/blog/rtabench-250902',
+        externalLink: 'https://www.velodb.io/blog/1465',
+    },
+    {
+        path: '/blog/sf-technology-replaced-presto-with-apache-doris',
+        externalLink: 'https://www.velodb.io/blog/1433',
+    },
+    {
+        path: '/blog/stability-at-scale-how-apache-doris-handles-pressure',
+        externalLink: 'https://www.velodb.io/blog/1449',
+    },
+    {
+        path: 
'/blog/telecom-giant-journey-from-clickhouse-to-apache-doris-13pb-in-one-table',
+        externalLink: 'https://www.velodb.io/blog/1440',
+    },
+    {
+        path: '/blog/tencent-music-migrate-elasticsearch-to-doris',
+        externalLink: 'https://www.velodb.io/blog/1395',
+    },
+    {
+        path: 
'/blog/top-commercial-bank-migrated-from-elasticsearch-to-apache-doris-for-pb-scale-log-storage-and-analytics',
+        externalLink: 'https://www.velodb.io/blog/1410',
+    },
+    {
+        path: 
'/blog/unified-lakehouse-with-apache-doris-and-paimon-xiaomi-achieves-6×-faster-performance',
+        externalLink: 'https://www.velodb.io/blog/1461',
+    },
+    {
+        path: '/blog/variant-in-apache-doris-2.1',
+        externalLink: 'https://www.velodb.io/blog/224',
+    },
+    {
+        path: '/blog/which-powers-observability-better',
+        externalLink: 'https://www.velodb.io/blog/1406',
+    },
+    {
+        path: 
'/blog/why-apache-doris-is-best-alternatives-for-real-time-analytics',
+        externalLink: 
'https://medium.com/@kxiao.tiger/apache-doris-vs-elasticsearch-6f7c8232e012',
+    },
+];
diff --git a/src/theme/BlogPostItem/index.tsx b/src/theme/BlogPostItem/index.tsx
index 02261174b63..d9e30c905f0 100644
--- a/src/theme/BlogPostItem/index.tsx
+++ b/src/theme/BlogPostItem/index.tsx
@@ -5,7 +5,10 @@ import BlogPostItemContainer from 
'@theme/BlogPostItem/Container';
 import BlogPostItemHeader from '@theme/BlogPostItem/Header';
 import BlogPostItemContent from '@theme/BlogPostItem/Content';
 import BlogPostItemFooter from '@theme/BlogPostItem/Footer';
+import useIsBrowser from '@docusaurus/useIsBrowser';
+import { Redirect } from '@docusaurus/router';
 import type { Props } from '@theme/BlogPostItem';
+import { BLOG_RELATED_EXTERNAL_LINK } from './blog.data';
 
 import './styles.scss';
 
@@ -15,8 +18,18 @@ function useContainerClassName() {
     return !isBlogPostPage ? 'margin-bottom--xl' : undefined;
 }
 
-export default function BlogPostItem({ children, className }: Props): 
JSX.Element {
+export default function BlogPostItem({ children, className }: Props): 
React.ReactElement {
     const containerClassName = useContainerClassName();
+    const isBrowser = useIsBrowser();
+    if (isBrowser) {
+        for (let item of BLOG_RELATED_EXTERNAL_LINK) {
+            if (location.pathname.startsWith(item.path)) {
+                window.location.href = item.externalLink;
+                return;
+            }
+        }
+    }
+
     return (
         <BlogPostItemContainer className={clsx(containerClassName, className)}>
             <BlogPostItemHeader />


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to