MongoDB - noSQL-database for irregular JSON data.
У 2016-му році я вперше познайомився з MongoDB і мені дуже сподобалось! Спочатку хочу трошки розповісти про ідею MongoDB. Загалом ідея цієї бази полягає в тому, щоб зберігати на діск іррегулярний JSON та відбирати з цього сховища JSON дещо по власним критеріям.
Наприклад запис 3 має ось такий JSON, як на першому скріні, а дев'ятий JSON має вигляд, як на другому скріні. На ції скрінах можна дуже добре побачити, чим відрізняються ці два JSON - перши має пустий об'єкт skills, а другий JSON maє skills з двох об'єктів. Це не просто звичайна ієрархічна структура, а іррегулярна структура, кожен збережений JSON може відрізнятися від попереднього. Третій та четверти скріни пояснюють це у текстовому та табличному вигляді.
Щоб працювати з MongoDB потрібно вирішити декілька питань. Перше питання - це інсталяція. Вона тривіальна.
Але для того, щоб запустити MongoDB у вигляді сервіса - потрібно дещо зробити самостійно. Це нагадує запуск MySQL та PosgreSQL - потрібно зробити файлову структуру для бази, відкрити порти для сервіса та зробити конфіг сервіса, у якому буде вказано порти та шлях до бази на діскі.
У моєму випадку я зробив ось такий конфіг:
1: storage:
2: dbPath: c:\mongo\db\
3: mmapv1:
4: smallFiles: true
5: engine: mmapv1
6: journal:
7: enabled: true
8: systemLog:
9: destination: file
10: path: c:\mongo\log\log.txt
11: net:
12: port: 27017
13: bindIp: 127.0.0.1
Після ціх кроків сервіс стартовав:
Наступний дуже простий крок, необхідний щоб працювати з базою - це інсталяція GUI, що працює з двигуном бази. Я вибрав MongoVUE. Цей вибір нагадує вибір MS SMS для MS SQL, MySQL Workbench для MS SQL, SQLAdmin для SQLLite та pgAdmin для PostgreSQL.
Наступний крок - це mongo-csharp-driver, який дозволяє працювати з базою програмно. Я записав усі зборки для роботі з MongoDB у той же самий каталог, де у мене зберігається база Mongo.
Наступний крок не має безпосереднього відношення до MongoDB, але без цього кроку працювати з JSON неможливо. Цей крок - інсталяція сборки Newtonsoft.JSON. І цю збірку, і збірку драйера MongoDB можливо інсталювать безпосередньо із студії за допомогою NUGET:
Ось тепер у нас є все, що необхідно для утворення проекту. Тільки потрібно без помилок зрозуміти версію NET, версію MongoDB, версію MongoCSharpDriver. У моєму середовище це виглядає ось так:
Взагалі збірки роботи з Mongo можна поставити і у GAC - це буде корисно, якщо ви маєте бажання вивчати мову запитів із MongoDB за допомогою LinqPAD.
I тепер ми дійшли до того стану, що вже можемо починати програмування з MongoDB. Взагалі тут багато чого можливо, мова запросів до бази з JSON достатньо продвинута, дивиться документацію на Mongo, тому я покажу тут лише невеличкий код, який зберігає в базу JSON, а потім вичитує JSON із бази, але парадигма роботи з даними JSON повинна бути зрозуміла з цього приклада.
1: Module Mongo
2:
3: Function ParseUpworkToMongoDB(Html As String) As Integer
4: Dim Pos1 As Integer = Html.IndexOf("var phpVars = {")
5: If Pos1 > 0 Then
6: Dim Pos2 As Integer = Html.IndexOf("}};", Pos1)
7: If Pos2 > 0 Then
8: Dim Counters As String = Html.Substring(Pos1 + 14, Pos2 - Pos1 - 12)
9: Dim JS As Newtonsoft.Json.Linq.JObject = Newtonsoft.Json.JsonConvert.DeserializeObject(Counters)
10: Dim db1 As New ParserDBDataContext
11: Dim MongoClient = New MongoDB.Driver.MongoClient("mongodb://localhost:27017/")
12: Dim MongoServers As MongoDB.Driver.MongoServer = MongoClient.GetServer
13: If MongoServers.Instances.Length > 0 Then
14: Dim MNDB As MongoDB.Driver.MongoDatabase = MongoServers.GetDatabase("jobs")
15: Dim Jobs = MNDB.GetCollection("Job")
16: Dim I As Integer = 1
17: For Each One In JS("jobs")
18: Dim X As MongoDB.Bson.BsonDocument = MongoDB.Bson.BsonDocument.Parse(One.ToString)
19: Jobs.Insert(X)
20: I += 1
21: Next
22: Return I
23: Else
24: Return 0
25: End If
26: Else
27: Return 0
28: End If
29: Else
30: Return 0
31: End If
32: End Function
На цьому невеличкому фрагменті ви можете побачити, як я спочатку знайшов у HTML потрібний мені JSON (стрічка 1-8), який складається на кожній сторінці з декількох об'єктів JOB. Потім я у стрічці 9 цей JSON за допомогою Newtonsoft.JSON перетворив на окремі об'єкти JOB. У стрічці 11 я зробив екземпляр об'єкту драйвера з конектом. Зрозуміло, що більш гнучкий код потребує цей конект винести у конфиг, але у ціей програмі мені було цього достатньо. Потім у стрічці 12-13 я подивився, чи працює двигун MongoDB - а якщо так, то у стрічці 14 отворив для роботи базу JOBS і зробив у неї колекцію JOB (аналог табли у SQL). Потім у стрічці 17 отримав черговий фрагмент JOB (а на моєї HTML-сторінці їх багато) і зберіг цей JSON у базу у стрічці 19. Перед тим отримавши у стрічці 18 специфічний об'єкт, який можливо зберігати у базу Mongo.
Саме таким чином я отримав дані, які ви можете побачити на початку цієї сторінки.
А далі мені у ціеї програмі були потрібні дані SKILL у вигляді SQL. Це я зробив ось таким кодом, який, мабуть, детально пояснювати вже не має сенсу, бо ви все вже зрозуміли.
35: Private Sub LoadSkillFromMongoDB()
36: Dim db1 As New ParserDBDataContext
37: Dim MongoClient = New MongoDB.Driver.MongoClient("mongodb://localhost:27017/")
38: Dim MongoServers As MongoDB.Driver.MongoServer = MongoClient.GetServer
39: If MongoServers.Instances.Length > 0 Then
40: Dim MNDB As MongoDB.Driver.MongoDatabase = MongoServers.GetDatabase("jobs")
41: Dim Jobs = MNDB.GetCollection("Job").FindAll
42: For Each One In Jobs
43: 'Debug.Print(One.ToString)
44: If One.GetElement("skills") IsNot Nothing Then
45: Dim OneVal = One.GetElement("skills")
46: If OneVal.Value.IsBsonArray Then
47: If OneVal.Value.ToString <> "[]" Then
48: '"[{ "name" : ".net-framework", "prettyName" : ".NET Framework" }, { "name" : "salesforce-apex", "prettyName" : "Salesforce Apex" }, { "name" : "visualforce", "prettyName" : "visualforce" }]"
49: Dim JS As Newtonsoft.Json.Linq.JArray = Newtonsoft.Json.JsonConvert.DeserializeObject(OneVal.Value.ToString)
50: For Each X In JS
51: '"{ "name": ".net-framework", "prettyName": ".NET Framework" }"
52: 'Debug.Print(X("prettyName").ToString)
53: 'db1.Cats.InsertOnSubmit(New Cat With {.TXT = X("prettyName").ToString})
54: db1.SubmitChanges()
55: Next
56:
57: End If
58: End If
59: End If
60: Next
61: End If
62: End Sub
63: End Module
Саме таким чином я отримав лист з усіма спеціальностями програмістів, що мені був потрібен для подальшої обробки.
Далі я покажу ще один дуже цікавий приклад, коли використання MongoDB дуже корисно. У мене є свій відео-сервер, а також я деякі відео викладаю у Ютюб. Але як зробили перелік усіх моїх відео, щоб порівняти перелік відео на моєму сервері та на сервері Ютюба? І там і там відео дуже багато і руками дуже важко зробити цей перелік. Тому доведеться використати YouTube Data API.
Першим кроком, вводимо ID каналу у форму пошуку каналів https://developers.google.com/youtube/v3/docs/channels/list, наприклад UCDxUCKh5eNy9iYYm3Slydzw та параметр part=contentDetails. Ми повинні отримати перелік токенів, з яких нас буде цікавити токен Uploads.
Таким же чином можна отримати перелік плей-листів, для цього потрібно на формі https://developers.google.com/youtube/v3/docs/playlists/list задати channelId та part=contentDetails. А потім можна і отримати перелік усіх відео у кожному прей-листі.
Якщо нам потрібно отримати перелік усіх відео з описом, то беремо номер каналу Uploads (наприклад на моєму скріні це "UUDxUCKh5eNy9iYYm3Slydzw") і далі задаємо цей номер каналу для форми https://developers.google.com/youtube/v3/docs/playlistItems/list. Щоб отримати можливість задати всі параметри, замість першої сторінки даних, переходимо у Load in APIs Explorer. Там рухаємося по всім сторінкам, задаючи тег NextPage. Таким чином ми отримуємо перелік усіх відео по сторінкам, кожного разу задаючи новий номер сторінки.
А далі отримані описи відео ми зберігаємо в базу MongoDB:
А далі за допомогою такого ж шаблонного коду, як і вище, я прочитав дані із MongoDB та переписав їх у реляційну базу (бо мій власний відео-сервер працює з реляційною базою і мені потрібно будо синхронізувати дещо з відео).
1: Module Module1
2: Sub Main()
3: 'SaveVideoList1()
4: 'SaveVideoList2()
5: GetTable()
6: End Sub
7:
8: Sub GetTable()
9: Dim db1 As New YoutubeVideoDBDataContext
10: Dim V = (From X In db1.MyYoutubeVideos Select X Order By X.position).ToList
11: Dim T As New Text.StringBuilder("<table>")
12: For Each X In V
13: T.Append("<tr><td>")
14: T.Append(X.position.ToString)
15: T.Append("</td><td>")
16: T.Append(CDate(X.publishedAt).ToShortDateString)
17: T.Append("</td><td>")
18: T.Append(X.videoId)
19: T.Append("</td><td><a href='https://www.youtube.com/watch?v=")
20: T.Append(X.videoId)
21: T.Append("'>")
22: T.Append(X.title)
23: T.AppendLine("</a></td></tr>")
24: Next
25: T.Append("</table>")
26: My.Computer.FileSystem.WriteAllText("G:\Projects\YoutubeVideoList\YoutubeVideoList\Videotable.txt", T.ToString, False)
27: End Sub
28: Sub SaveVideoList2()
29: Dim db1 As New YoutubeVideoDBDataContext
30: Dim MongoClient = New MongoDB.Driver.MongoClient("mongodb://localhost:27017/")
31: Dim MongoServers As MongoDB.Driver.MongoServer = MongoClient.GetServer
32: If MongoServers.Instances.Length > 0 Then
33: Dim MNDB As MongoDB.Driver.MongoDatabase = MongoServers.GetDatabase("Youtube")
34: Dim Jobs = MNDB.GetCollection("PageList").FindAll
35: For Each One In Jobs
36: If One.GetElement("items") IsNot Nothing Then
37: Dim OneVal = One.GetElement("items")
38: If OneVal.Value.IsBsonArray Then
39: If OneVal.Value.ToString <> "[]" Then
40: Dim JS As Newtonsoft.Json.Linq.JArray = Newtonsoft.Json.JsonConvert.DeserializeObject(OneVal.Value.ToString)
41: For Each X In JS
42: Dim Y = New MyYoutubeVideo With {
43: .description = X.Item("snippet")("description").ToString,
44: .high_height = X.Item("snippet")("thumbnails")("high")("height").ToString,
45: .high_width = X.Item("snippet")("thumbnails")("high")("width").ToString,
46: .position = X.Item("snippet")("position").ToString,
47: .publishedAt = X.Item("snippet")("publishedAt").ToString,
48: .title = X.Item("snippet")("title").ToString,
49: .videoId = X.Item("snippet")("resourceId")("videoId").ToString
50: }
51: If X.Item("snippet")("thumbnails")("maxres") IsNot Nothing Then
52: Y.maxres_height = X.Item("snippet")("thumbnails")("maxres")("height").ToString
53: Y.maxres_width = X.Item("snippet")("thumbnails")("maxres")("width").ToString
54: End If
55: db1.MyYoutubeVideos.InsertOnSubmit(Y)
56: db1.SubmitChanges()
57: Next
58: End If
59: End If
60: End If
61: Next
62: End If
63: End Sub
64:
65: Sub SaveVideoList1()
66: Dim db1 As New YoutubeVideoDBDataContext
67: Dim MongoClient = New MongoDB.Driver.MongoClient("mongodb://localhost:27017/")
68: Dim MongoServers As MongoDB.Driver.MongoServer = MongoClient.GetServer
69: If MongoServers.Instances.Length > 0 Then
70: Dim MNDB As MongoDB.Driver.MongoDatabase = MongoServers.GetDatabase("Youtube")
71: Dim Jobs = MNDB.GetCollection("PlayList").FindAll
72: For Each One In Jobs
73: If One.GetElement("items") IsNot Nothing Then
74: Dim OneVal = One.GetElement("items")
75: If OneVal.Value.IsBsonArray Then
76: If OneVal.Value.ToString <> "[]" Then
77: Dim JS As Newtonsoft.Json.Linq.JArray = Newtonsoft.Json.JsonConvert.DeserializeObject(OneVal.Value.ToString)
78: For Each X In JS
79: db1.MyToutubeVideoLists.InsertOnSubmit(New MyToutubeVideoList With {.playlistId = X.Item("id")("playlistId").ToString, .title = X.Item("snippet")("title").ToString})
80: db1.SubmitChanges()
81: Next
82: End If
83: End If
84: End If
85: Next
86: End If
87: End Sub
88: End Module
Саме таким чином я отримав ось цю таблу, яку далі я почав синхронізувати с відео на своєму власному мультікаст сервері.
More example of using Google API
- Use Google JS API
- How to build application server based on push notification from Firebase
- Parse Yotube response by Newtonsoft.Json
- Send mails via Gmail
|