95道MongoDB面試題(含答案),1萬字詳細解析!

1、mongodb是什麼?

MongoDB 是由 C++語言編寫的,是一個基於分佈式文件存儲的開源數據庫系統。 再高負載的情況下,添加更多的節點,可以保證服務器性能。 MongoDB 旨在給 WEB 應用提供可擴展的高性能數據存儲解決方案。

MongoDB 將數據存儲爲一個文檔,數據結構由鍵值(key=>value)對組成。 MongoDB 文檔類似於 JSON 對象。字段值可以包含其他文檔,數組及文檔數組。

2、mongodb有哪些特點?

(1)MongoDB 是一個面向文檔存儲的數據庫,操作起來比較簡單和容易。

(2)你可以在 MongoDB 記錄中設置任何屬性的索引 (如: FirstName="Sameer",Address="8 Gandhi Road")來實現更快的排序。

(3)你可以通過本地或者網絡創建數據鏡像,這使得 MongoDB 有更強的擴展性。

(4)如果負載的增加(需要更多的存儲空間和更強的處理能力) ,它可以分佈在計算機網絡中的其他節點上這就是所謂的分片。

(5)Mongo 支持豐富的查詢表達式。查詢指令使用 JSON 形式的標記,可輕易查詢文檔中內嵌的對象及數組。

(6)MongoDb 使用 update()命令可以實現替換完成的文檔(數據)或者一些指定的數據字段 。

(7)Mongodb 中的 Map/reduce 主要是用來對數據進行批量處理和聚合操作。

(8)Map 和 Reduce。 Map 函數調用 emit(key,value)遍歷集合中所有的記錄,將 key 與 value 傳給 Reduce 函數進行處理。

(9)Map 函數和 Reduce 函數是使用 Javascript 編寫的,並可以通過 db.runCommand 或 mapreduce 命令來執行 MapReduce 操作。

(10)GridFS 是 MongoDB 中的一個內置功能,可以用於存放大量小文件。

(11) MongoDB 允許在服務端執行腳本, 可以用 Javascript 編寫某個函數,直接在服務端執行,也可以把函數的定義存儲在服務端,下次直接調用即可。

3、你說的NoSQL數據庫是什麼意思?NoSQL與RDBMS直接有什麼區別?爲什麼要使用和不使用NoSQL數據庫?說一說NoSQL數據庫的幾個優點?

NoSQL是非關係型數據庫,NoSQL = Not Only SQL。

關係型數據庫採用的結構化的數據,NoSQL採用的是鍵值對的方式存儲數據。

在處理非結構化/半結構化的大數據時;在水平方向上進行擴展時;隨時應對動態增加的數據項時可以優先考慮使用NoSQL數據庫。

再考慮數據庫的成熟度;支持;分析和商業智能;管理及專業性等問題時,應優先考慮關係型數據庫。

4、NoSQL數據庫有哪些類型?

NoSQL數據庫的類型

例如:MongoDB, Cassandra, CouchDB, Hypertable, Redis, Riak, HBASE, Memcache

5、MySQL與MongoDB之間最基本的差別是什麼?

MySQL和MongoDB兩者都是免費開源的數據庫。MySQL和MongoDB有許多基本差別包括數據的表示(data representation),查詢,關係,事務,schema的設計和定義,標準化(normalization),速度和性能。

通過比較MySQL和MongoDB,實際上我們是在比較關係型和非關係型數據庫,即數據存儲結構不同。

6、你怎麼比較MongoDB、CouchDB及CouchBase?

MongoDB和CouchDB都是面向文檔的數據庫。MongoDB和CouchDB都是開源NoSQL數據庫的最典型代表。 除了都以文檔形式存儲外它

們沒有其他的共同點。MongoDB和CouchDB在數據模型實現、接口、對象存儲以及複製方法等方面有很多不同。

7、MongoDB成爲最好NoSQL數據庫的原因是什麼?

以下特點使得MongoDB成爲最好的NoSQL數據庫:

  • 面向文件的
  • 高性能
  • 高可用性
  • 易擴展性
  • 豐富的查詢語言

8、journal回放在條目(entry)不完整時(比如恰巧有一箇中途故障了)會遇到問題嗎?

每個journal (group)的寫操作都是一致的,除非它是完整的否則在恢復過程中它不會回放。

9、分析器在MongoDB中的作用是什麼?

MongoDB中包括了一個可以顯示數據庫中每個操作性能特點的數據庫分析器。通過這個分析器你可以找到比預期慢的查詢(或寫操作);利用這一信息,比如,可以確定是否需要添加索引。

10、名字空間(namespace)是什麼?

MongoDB存儲BSON對象在叢集(collection)中。數據庫名字和叢集名字以句點連結起來叫做名字空間(namespace)。

11、 如果用戶移除對象的屬性,該屬性是否從存儲層中刪除?

是的,用戶移除屬性然後對象會重新保存(re-save())。

12、能否使用日誌特徵進行安全備份?

是的。

13、允許空值null嗎?

對於對象成員而言,是的。然而用戶不能夠添加空值(null)到數據庫叢集(collection)因爲空值不是對象。然而用戶能夠添加空對象{}。

14、更新操作立刻fsync到磁盤?

不會,磁盤寫操作默認是延遲執行的。寫操作可能在兩三秒(默認在60秒內)後到達磁盤。例如,如果一秒內數據庫收到一千個對一個對象遞增的操作,僅刷新磁盤一次。(注意,儘管fsync選項在命令行和經過getLastError_old是有效的)

15、如何執行事務/加鎖?

MongoDB沒有使用傳統的鎖或者複雜的帶回滾的事務,因爲它設計的宗旨是輕量,快速以及可預計的高性能。可以把它類比成MySQLMylSAM的自動提交模式。通過精簡對事務的支持,性能得到了提升,特別是在一個可能會穿過多個服務器的系統裏。

16、爲什麼我的數據文件如此龐大?

MongoDB會積極的預分配預留空間來防止文件系統碎片。

17、啓用備份故障恢復需要多久?

從備份數據庫聲明主數據庫宕機到選出一個備份數據庫作爲新的主數據庫將花費10到30秒時間。這期間在主數據庫上的操作將會失敗--包括

寫入和強一致性讀取(strong consistent read)操作。然而,你還能在第二數據庫上執行最終一致性查詢(eventually consistent query)(在slaveOk模式下),即使在這段時間裏。

18、什麼是master或primary?

它是當前備份集羣(replica set)中負責處理所有寫入操作的主要節點/成員。在一個備份集羣中,當失效備援(failover)事件發生時,一個另外的成員會變成primary。

19、什麼是secondary或slave?

Seconday從當前的primary上覆制相應的操作。它是通過跟蹤複製oplog(local.oplog.rs)做到的。

20、我必須調用getLastError來確保寫操作生效了麼?

不用。不管你有沒有調用getLastError(又叫"Safe Mode")服務器做的操作都一樣。調用getLastError只是爲了確認寫操作成功提交了。當然,你經常想得到確認,但是寫操作的安全性和是否生效不是由這個決定的。

21、我應該啓動一個集羣分片(sharded)還是一個非集羣分片的 MongoDB 環境?

爲開發便捷起見,我們建議以非集羣分片(unsharded)方式開始一個 MongoDB 環境,除非一臺服務器不足以存放你的初始數據集。從非集羣分片升級到集羣分片(sharding)是無縫的,所以在你的數據集還不是很大的時候沒必要考慮集羣分片(sharding)。

22、分片(sharding)和複製(replication)是怎樣工作的?

每一個分片(shard)是一個分區數據的邏輯集合。分片可能由單一服務器或者集羣組成,我們推薦爲每一個分片(shard)使用集羣。

23、數據在什麼時候纔會擴展到多個分片(shard)裏?

MongoDB 分片是基於區域(range)的。所以一個集合(collection)中的所有的對象都被存放到一個塊(chunk)中。只有當存在多餘一個塊的時後,纔會有多個分片獲取數據的選項。現在,每個默認塊的大小是 64Mb,所以你需要至少 64 Mb 空間纔可以實施一個遷移。

24、當我試圖更新一個正在被遷移的塊(chunk)上的文檔時會發生什麼?

更新操作會立即發生在舊的分片(shard)上,然後更改纔會在所有權轉移(ownership transfers)前複製到新的分片上。

25、如果在一個分片(shard)停止或者很慢的時候,我發起一個查詢會怎樣?

如果一個分片(shard)停止了,除非查詢設置了“Partial”選項,否則查詢會返回一個錯誤。如果一個分片(shard)響應很慢,MongoDB則會等待它的響應。

26、我可以把moveChunk目錄裏的舊文件刪除嗎?

沒問題,這些文件是在分片(shard)進行均衡操作(balancing)的時候產生的臨時文件。一旦這些操作已經完成,相關的臨時文件也應該被刪除掉。但目前清理工作是需要手動的,所以請小心地考慮再釋放這些文件的空間。

27、我怎麼查看 Mongo 正在使用的鏈接?

db._adminCommand("connPoolStats");

28、如果塊移動操作(moveChunk)失敗了,我需要手動清除部分轉移的文檔嗎?

不需要,移動操作是一致(consistent)並且是確定性的(deterministic);一次失敗後,移動操作會不斷重試;當完成後,數據只會出現在新的分片裏(shard)。

29、如果我在使用複製技術(replication),可以一部分使用日誌(journaling)而其他部分則不使用嗎?

可以。

30、當更新一個正在被遷移的塊(Chunk)上的文檔時會發生什麼?

更新操作會立即發生在舊的塊(Chunk)上,然後更改纔會在所有權轉移前複製到新的分片上。

31、MongoDB在A:{B,C}上建立索引,查詢A:{B,C}和A:{C,B}都會使用索引嗎?

不會,只會在A:{B,C}上使用索引。

32、如果一個分片(Shard)停止或很慢的時候,發起一個查詢會怎樣?

如果一個分片停止了,除非查詢設置了“Partial”選項,否則查詢會返回一個錯誤。如果一個分片響應很慢,MongoDB會等待它的響應。

33、MongoDB支持存儲過程嗎?如果支持的話,怎麼用?

MongoDB支持存儲過程,它是javascript寫的,保存在db.system.js表中。

34、如何理解MongoDB中的GridFS機制,MongoDB爲何使用GridFS來存儲文件?

GridFS是一種將大型文件存儲在MongoDB中的文件規範。使用GridFS可以將大文件分隔成多個小文檔存放,這樣我們能夠有效的保存大文檔,而且解決了BSON對象有限制的問題。

35、什麼是NoSQL數據庫?NoSQL和RDBMS有什麼區別?在哪些情況下使用和不使用NoSQL數據庫?

NoSQL是非關係型數據庫,NoSQL = Not Only SQL。

關係型數據庫採用的結構化的數據,NoSQL採用的是鍵值對的方式存儲數據。

在處理非結構化/半結構化的大數據時;在水平方向上進行擴展時;隨時應對動態增加的數據項時可以優先考慮使用NoSQL數據庫。

在考慮數據庫的成熟度;支持;分析和商業智能;管理及專業性等問題時,應優先考慮關係型數據庫。

36、MongoDB支持存儲過程嗎?如果支持的話,怎麼用?

MongoDB支持存儲過程,它是javascript寫的,保存在db.system.js表中。

37、如何理解MongoDB中的GridFS機制,MongoDB爲何使用GridFS來存儲文件?

GridFS是一種將大型文件存儲在MongoDB中的文件規範。使用GridFS可以將大文件分隔成多個小文檔存放,這樣我們能夠有效的保存大文檔,而且解決了BSON對象有限制的問題。

38、爲什麼MongoDB的數據文件很大?

MongoDB採用的預分配空間的方式來防止文件碎片。

39、當更新一個正在被遷移的塊(Chunk)上的文檔時會發生什麼?

更新操作會立即發生在舊的塊(Chunk)上,然後更改纔會在所有權轉移前複製到新的分片上。

40、MongoDB在A:{B,C}上建立索引,查詢A:{B,C}和A:{C,B}都會使用索引嗎?

不會,只會在A:{B,C}上使用索引。

41、如果一個分片(Shard)停止或很慢的時候,發起一個查詢會怎樣?

如果一個分片停止了,除非查詢設置了“Partial”選項,否則查詢會返回一個錯誤。如果一個分片響應很慢,MongoDB會等待它的響應。

42、分析器在MongoDB中的作用是什麼?

分析器就是explain 顯示每次操作性能特點的數據庫分析器。通過分析器可能查找比預期慢的操作

43、如果用戶移除對象的屬性,該屬性是否從存儲層中刪除?

是的,用戶移除屬性然後對象會重新保存(re-save())。

44、能否使用日誌特徵進行安全備份?

是的

45、更新操作立刻fsync到磁盤?

一般磁盤的寫操作都是延遲執行的

46、如何執行事務/加鎖?

因爲mongodb設計就是輕量高性能,所以沒有傳統的鎖和複雜的事務的回滾

47、什麼是master或primary?

當前備份集羣負責所有的寫入操作的主要節點,在集羣中,當主節點(master)失效,另一個成員會變爲master

48、getLastError的作用

調用getLastError 可以確認當前的寫操作是否成功的提交

49、分片(sharding)和複製(replication)是怎樣工作的?

分片可能是單一的服務器或者集羣組成,推薦使用集羣

50、數據在什麼時候纔會擴展到多個分片(shard)裏?

mongodb分片是基於區域的,所以一個集合的所有對象都放置在同一個塊中,只有當存在多餘一個塊的時候,纔會有多個分片獲取數據的選項

51、 當我試圖更新一個正在被遷移的塊(chunk)上的文檔時會發生什麼?

會立即更新舊的分片,然後更改纔會在所有權轉移前複製到新的分片上

52、 我怎麼查看 Mongo 正在使用的鏈接?

db._adminCommand("connPoolStats");

53、mongodb的結構介紹

數據庫中存儲的對象設計bson,一種類似json的二進制文件,由鍵值對組成

54、數據庫的整體結構

鍵值對–》文檔–》集合–》數據庫

55、MongoDB是由哪種語言寫的

MongoDB用c++編寫的,流行的開源數據庫MySQL也是用C++開發的。C++1983年發行是一種使用廣泛的計算機程序設計語言。它是一種痛用程序設計語言,支持 多種編程模式。

56、MongoDB的優勢有哪些

  • 面向文檔的存儲:以 JSON 格式的文檔保存數據。
  • 任何屬性都可以建立索引。
  • 複製以及高可擴展性。
  • 自動分片。
  • 豐富的查詢功能。
  • 快速的即時更新。
  • 來自 MongoDB 的專業支持。

57、什麼是集合

集合就是一組 MongoDB 文檔。它相當於關係型數據庫(RDBMS)中的表這種概念。集合位於單獨的一個數據庫中。一個集合內的多個文檔可以有多個不同的字段。一般來說,集合中的文檔都有着相同或相關的目的。

58、什麼是文檔

文檔由一組key value組成。文檔是動態模式,這意味着同一集合裏的文檔不需要有相同的字段和結構。在關係型數據庫中table中的每一條記錄相當於MongoDB中的一個文檔。

59、什麼是”mongod“

mongod是處理MongoDB系統的主要進程。它處理數據請求,管理數據存儲,和執行後臺管理操作。當我們運行mongod命令意味着正在啓動MongoDB進程,並且在後臺運行。

60、"mongod"參數有什麼

  • 傳遞數據庫存儲路徑,默認是"/data/db"
  • 端口號 默認是 "27017"

61、什麼是"mongo"

它是一個命令行工具用於連接一個特定的mongod實例。當我們沒有帶參數運行mongo命令它將使用默認的端口號和localhost連接

62、MongoDB哪個命令可以切換數據庫

MongoDB 用 use +數據庫名稱的方式來創建數據庫。 use 會創建一個新的數據庫,如果該數據庫存在,則返回這個數據庫。

63、什麼是非關係型數據庫

非關係型數據庫是對不同於傳統關係型數據庫的統稱。非關係型數據庫的顯著特點是不使用SQL作爲查詢語言,數據存儲不需要特定的表格模式。由於簡單的設計和非常好的性能所以被用於大數據和Web Apps等

64、非關係型數據庫有哪些類型

  • -Key-Value 存儲 Eg:Amazon S3
  • 圖表 Eg:Neo4J
  • 文檔存儲 Eg:MongoDB
  • 基於列存儲 Eg:Cassandra

65、爲什麼用MOngoDB?

  • 架構簡單
  • 沒有複雜的連接
  • 深度查詢能力,MongoDB支持動態查詢。
  • 容易調試
  • 容易擴展
  • 不需要轉化/映射應用對象到數據庫對象
  • 使用內部內存作爲存儲工作區,以便更快的存取數據。

66、在哪些場景使用MongoDB

  • 大數據
  • 內容管理系統
  • 移動端Apps
  • 數據管理

67、MongoDB中的命名空間是什麼意思?

MongoDB內部有預分配空間的機制,每個預分配的文件都用0進行填充。

數據文件每新分配一次,它的大小都是上一個數據文件大小的2倍,每個數據文件最大2G。

MongoDB每個集合和每個索引都對應一個命名空間,這些命名空間的元數據集中在16M的*.ns文件中,平均每個命名佔用約 628 字節,也即整個數據庫的命名空間的上限約爲24000。

如果每個集合有一個索引(比如默認的_id索引),那麼最多可以創建12000個集合。如果索引數更多,則可創建的集合數就更少了。同時,如果集合數太多,一些操作也會變慢。

要建立更多的集合的話,MongoDB 也是支持的,只需要在啓動時加上“--nssize”參數,這樣對應數據庫的命名空間文件就可以變得更大以便保存更多的命名。這個命名空間文件(.ns文件)最大可以爲 2G。

每個命名空間對應的盤區不一定是連續的。與數據文件增長相同,每個命名空間對應的盤區大小都是隨分配次數不斷增長的。目的是爲了平衡命名空間浪費的空間與保持一個命名空間數據的連續性。

需要注意的一個命名空間$freelist,這個命名空間用於記錄不再使用的盤區(被刪除的Collection或索引)。每當命名空間需要分配新盤區時,會先查看$freelist是否有大小合適的盤區可以使用,如果有就回收空閒的磁盤空間。

68、哪些語言支持MongoDB?

C、C++、C#、Java、Node.js、Perl、Php 等

69、在MongoDB中如何創建一個新的數據庫

MongoDB 用 use + 數據庫名稱 的方式來創建數據庫。 use 會創建一個新的數據庫,如果該數據庫存在,則返回這個數據庫。

70、在MongoDB中如何查看數據庫列表

使用命令"show dbs"

71、MongoDB中的分片是什麼意思

分片是將數據水平切分到不同的物理節點。當應用數據越來越大的時候,數據量也會越來越大。當數據量增長時,單臺機器有可能無法存儲數據或可接受的讀取寫入吞吐量。利用分片技術可以添加更多的機器來應對數據量增加以及讀寫操作的要求。

72、如何查看使用MongoDB的連接Sharding - MongoDB Manual21.如何查看使用MongoDB的連接

使用命令"db.adminCommand(“connPoolStats”)"

>db.adminCommand(“connPoolStats”)

73、什麼是複製

複製是將數據同步到多個服務器的過程,通過多個數據副本存儲到多個服務器上增加數據可用性。複製可以保障數據的安全性,災難恢復,無需停機維護(如備份,重建索引,壓縮),分佈式讀取數據。

74、在MongoDB中如何在集合中插入一個文檔

要想將數據插入 MongoDB 集合中,需要使用 insert() 或 save() 方法。

>db.collectionName.insert({"key":"value"})
>db.collectionName.save({"key":"value"})

75、在MongoDB中如何除去一個數據庫Collection Methods24.在MongoDB中如何除去一個數據庫

MongoDB 的 dropDatabase() 命令用於刪除已有數據庫。

>db.dropDatabase()

76、在MongoDB中如何創建一個集合。

在 MongoDB 中,創建集合採用db.createCollection(name, options)方法。 options 是一個用來指定集合配置的文檔。

>db.createCollection("collectionName")db.createCollection() - MongoDB Manual>db.createCollection("

77、在MongoDB中如何查看一個已經創建的集合

可以使用show collections 查看當前數據庫中的所有集合清單

>show collections

78、在MongoDB中如何刪除一個集合

MongoDB 利用 db.collection.drop() 來刪除數據庫中的集合。

>db.CollectionName.drop()

79、爲什麼要在MongoDB中使用分析器

數據庫分析工具(Database Profiler)會針對正在運行的mongod實例收集數據庫命令執行的相關信息。包括增刪改查的命令以及配置和管理命令。分析器(profiler)會寫入所有收集的數據到 system.profile集合,一個capped集合在管理員數據庫。分析器默認是關閉的你能通過per數據庫或per實例開啓。

80、MongoDB支持主鍵外鍵關係嗎

默認MongoDB不支持主鍵和外鍵關係。 用Mongodb本身的API需要硬編碼才能實現外鍵關聯,不夠直觀且難度較大。

81、MongoDB支持哪些數據類型

String、Integer、Double、Boolean、Object、Object ID、Arrays、Min/Max Keys、Datetime、Code、Regular Expression等

82、爲什麼要在MongoDB中用"Code"數據類型

"Code"類型用於在文檔中存儲 JavaScript 代碼。

83、爲什麼要在MongoDB中用"Regular Expression"數據類型

"Regular Expression"類型用於在文檔中存儲正則表達式

84、爲什麼在MongoDB中使用"Object ID"數據類型

"ObjectID"數據類型用於存儲文檔id

85、如何在集合中插入一個文檔

要想將數據插入 MongoDB 集合中,需要使用insert()或save()方法。

>db.collectionName.insert({"key":"value"})
>db.collectionName.save({"key":"value"})

86、"ObjectID"由哪些部分組成

一共有四部分組成:時間戳、客戶端ID、客戶進程ID、三個字節的增量計數器

_id是一個 12 字節長的十六進制數,它保證了每一個文檔的唯一性。在插入文檔時,需要提供 _id 。如果你不提供,那麼 MongoDB 就會爲每一文檔提供一個唯一的 id。 _id 的頭 4 個字節代表的是當前的時間戳,接着的後 3 個字節表示的是機器 id 號,接着的 2 個字節表示MongoDB 服務器進程 id,最後的 3 個字節代表遞增值。

87、在MongoDb中什麼是索引

索引用於高效的執行查詢.沒有索引MongoDB將掃描查詢整個集合中的所有文檔這種掃描效率很低,需要處理大量數據。索引是一種特殊的數據結構,將一小塊數據集保存爲容易遍歷的形式。索引能夠存儲某種特殊字段或字段集的值,並按照索引指定的方式將字段值進行排序。

88、如何添加索引

使用 db.collection.createIndex() 在集合中創建一個索引

>db.collectionName.createIndex({columnName:1})

89、用什麼方法可以格式化輸出結果

使用pretty() 方法可以格式化顯示結果

>db.collectionName.find().pretty()

90、如何使用"AND"或"OR"條件循環查詢集合中的文檔

在 find() 方法中,如果傳入多個鍵,並用逗號( , )分隔它們,那麼 MongoDB 會把它看成是AND條件。

>db.mycol.find({key1:value1, key2:value2}).pretty()

若基於OR條件來查詢文檔,可以使用關鍵字$or。

>db.mycol.find(
 {
  $or: [
    {key1: value1}, {key2:value2}
  ]
 }
).pretty()

91、在MongoDB中如何更新數據

update() 與 save() 方法都能用於更新集合中的文檔。 update() 方法更新已有文檔中的值,而 save() 方法則是用傳入該方法的文檔來替換已有文檔。

92、如何刪除文檔

MongoDB 利用 remove() 方法 清除集合中的文檔。它有 2 個可選參數:

  • deletion criteria:(可選)刪除文檔的標準。
  • justOne:(可選)如果設爲 true 或 1,則只刪除一個文檔。
>db.collectionName.remove({key:value})

93、在MongoDB中如何排序

MongoDB 中的文檔排序是通過 sort() 方法來實現的。 sort() 方法可以通過一些參數來指定要進行排序的字段,並使用 1 和 -1 來指定排

序方式,其中 1 表示升序,而 -1 表示降序。

>db.connectionName.find({key:value}).sort({columnName:1})

94、什麼是聚合

聚合操作能夠處理數據記錄並返回計算結果。聚合操作能將多個文檔中的值組合起來,對成組數據執行各種操作,返回單一的結果。它相當於 SQL 中的 count(*) 組合 group by。對於 MongoDB 中的聚合操作,應該使用 aggregate() 方法。

>db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)

95、在MongoDB中什麼是副本集

在MongoDB中副本集由一組MongoDB實例組成,包括一個主節點多個次節點,MongoDB客戶端的所有數據都寫入主節點(Primary),副節點從主節點同步寫入數據,以保持所有複製集內存儲相同的數據,提高數據可用性。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章