|
1 | 1 | # MOOGLE - The Worst Best Search Engine |
2 | 2 |
|
3 | | -## TODO |
4 | | -- [ ] Add a favicon |
5 | | -- [x] Add a redis instance to the docker-compose file |
6 | | -- [x] Check fuzzy finding and spell correction |
| 3 | +Moogle is a search engine designed for educational purposes. Inspired by early 2000s web architecture, Moogle aims to emulate a minimal but functional version of the search engine pipeline: crawling, indexing, and querying the web. |
7 | 4 |
|
8 | | -## For Future |
9 | | -- [ ] Use stems for words |
10 | | -- [ ] Check for words that could be hyphened or not (Megaman mega man mega-man). |
11 | | -- [x] Implement query filter service |
12 | | -- [ ] Handle weird queries like 'something+something' in the frontend |
| 5 | +## Features |
| 6 | +- **Page Searching**: Moogle allows users to search for web pages using keywords. The search results are ranked based on the PageRank algorithm and TF-IDF scoring. |
| 7 | +- **Image Searching**: Moogle can also search for images. |
| 8 | +- **Page Linking**: Moogle provides information about outlinks and backlinks for each page. This is useful for understanding the structure of the web and how pages are connected. |
| 9 | +- **Life Ain't Cringe**: A simple extra page that showcases a random page from the web each day and provides search engine data such as the most searched terms that day. |
13 | 10 |
|
14 | | -## Components |
| 11 | +## Architecture |
| 12 | +Moogle is built using a microservices architecture, where each component of the search engine is encapsulated in its own service. This allows for easy scaling and maintenance of individual components. All services are located in the `services` directory, and each service has its own Dockerfile for containerization. |
15 | 13 |
|
16 | | -- [x] Crawler |
17 | | -- [x] Indexer |
18 | | -- [x] Search engine |
19 | | -- [x] Backlinks |
20 | | -- [x] TFIDF |
21 | | -- [x] PageRank |
22 | | -- [x] Query filter |
23 | | -- [x] Frontend |
24 | | -- [ ] Monitoring |
| 14 | +Moogle uses Redis as a message broker and to store temporary data, and MongoDB as the primary database for storing indexed data. |
25 | 15 |
|
26 | | -## Top Priority |
27 | | -- [x] Images |
28 | | -- [x] Make frontend prettier |
29 | | -- [x] Docker images |
30 | | -- [x] Scaling up/down |
31 | | -- [x] Load balancing |
| 16 | +### Services |
| 17 | +- **Spider**: Responsible for crawling the web and fetching pages. It uses a simple breadth-first search algorithm to discover new links. It stores information in a Redis database for fast access. |
| 18 | +- **Indexer**: Takes the crawled pages and indexes them for fast retrieval. It uses a simple inverted index structure to map terms to documents. It processes the information the spider stored in Redis and stores the indexed data in a MongoDB database. |
| 19 | +- **Image Indexer**: Indexes images found on the crawled pages. It is essentially a different version of the indexer that focuses on images. It uses a similar inverted index structure to map image URLs to documents. |
| 20 | +- **Backlinks Processor**: Transfers backlinks data from Redis to MongoDB. It is a simple service that runs periodically to ensure that the backlinks data is up-to-date. |
| 21 | +- **Page Rank**: Calculates the PageRank of each page based on the backlinks data. It uses Google's original PageRank algorithm to determine the importance of each page. It stores the PageRank data in MongoDB. |
| 22 | +- **tf-idf**: Calculates the term frequency-inverse document frequency (TF-IDF) for each term in the indexed pages. It uses the TF-IDF algorithm to determine the importance of each term in the context of the entire collection of documents. It stores the TF-IDF data in MongoDB. |
| 23 | +- **Query Engine**: Essentially the backend of the search engine. It takes user queries and retrieves the relevant documents from the indexed data. It uses a simple keyword matching algorithm to find the most relevant documents. It also uses the PageRank and TF-IDF data to rank the results. |
| 24 | +- **Monitoring**: A simple service that monitors and spawns new instances of other services as needed. Currently it is not updated to work with the new architecture, but it is a placeholder for future development. |
| 25 | +- **Client**: A simple web client that allows users to interact with the search engine. It provides a 2000s-inspired interface for searching the web. It uses a simple HTML/CSS/JS stack and communicates with the backend services using REST APIs. |
32 | 26 |
|
33 | | - |
34 | | -## Install Redis |
35 | | -If you choose to use local Redis we strongly recommend using Docker. If you choose not to use Docker, use the following instructions based on your OS: |
| 27 | +## Repo Structure |
36 | 28 |
|
37 | 29 | ```bash |
38 | | -sudo docker run -d --name redis-stack -p 6379:6379 -p 8001:8001 redis/redis-stack:latest |
39 | | -sudo docker start redis-stack |
| 30 | +. |
| 31 | +├── migration/ |
| 32 | +├── services/ |
| 33 | +│ ├── spider/ |
| 34 | +│ ├── indexer/ |
| 35 | +│ ├── search-engine/ |
| 36 | +│ ├── client/ |
| 37 | +│ └── ... |
| 38 | +└── README.md |
40 | 39 | ``` |
41 | 40 |
|
42 | | -SILENCE TEST DRIVEN DEVEVLOPER |
43 | | - |
44 | | -## MESSAGE QUEUES |
45 | | -- `spider_queue`: ZSET |
46 | | -- `indexer_queue`: LIST |
47 | | -- `signal_queue`: LIST |
48 | | - |
49 | | -## REDIS KEYS |
50 | | -- `page_data:<normalized_page_url>`: HASH |
51 | | - - 1) "html" - string |
52 | | - - 2) "last_crawled" - timestamp |
53 | | -- `page_images:<normalized_page_url>`: SET { `<image_url>` } |
54 | | -- `image_data:<image_url>`: HASH |
55 | | - - 1) "normalized_page_url" - string |
56 | | - - 2) "alt" - string |
57 | | -This one will be used to check if it has been visited before |
58 | | -- `normalized_url:<normalized_page_url>`: HASH |
59 | | - - 1) "raw_url" - string |
60 | | - - 2) "visited" - integer (0 = false, 1 = true) |
61 | | - |
62 | | -## BOTH |
63 | | -Outlinks will be saved to storage db in the indexer |
64 | | -- `backlinks:<normalized_page_url>`: SET { `<normalized_page_url>` } |
65 | | -A different service will be in charge of saving and updating backlinks |
66 | | -- `outlinks:<normalized_page_url>`: SET { `<normalized_page_url>` } |
67 | | - |
68 | | - |
69 | | -## NOSQL DATA |
70 | | -- `word:<word>`: ZSET { `<normalized_page_url>`, SCORE } |
71 | | -- `word_images:<word>` ZSET { `<normalized_image_url>`, SCORE } |
72 | | -- `url_metadata:<normalized_page_url>`: HASH |
73 | | - - 1) "title" - integer |
74 | | - - 2) "summary_text" - string |
75 | | - - 3) "description" - string |
76 | | - - 4) "normalized_url" - string # I don't remember why I need this but I do |
77 | | - - 4) "raw_url" - string # I don't remember why I need this but I do |
78 | | - - 5) "last_crawled" - timestamp |
79 | | -- `image:<image_url>`: HASH |
80 | | - - 1) "normalized_page_url" - string |
81 | | - - 2) "alt" - string |
82 | | - - 3) "keywords" - List[string] |
83 | | - |
84 | | -## REDIS KEYS |
85 | | -- `backlinks:*`: SET { } |
86 | | - - set{ "normalized_page_url" } |
87 | | -- `outlinks:*`: SET |
88 | | - - set{ "normalized_page_url" } |
89 | | - |
90 | | -Crawl links and push page data to redis |
91 | | -Also push backlinks, outlinks, page_image |
92 | | - |
93 | | -These ones are only for transfering information to the indexer, can be deleted from the db so it's good to keep in redis |
94 | | -- `page_data:<normalized_page_url>`: HASH |
95 | | - - 1) "status_code" - integer |
96 | | - - 2) "content_type" - string |
97 | | - - 3) "normalized_url" - string |
98 | | - - 4) "html" - string |
99 | | - - 5) "last_crawled" - timestamp |
100 | | -- `page_images:<normalized_page_url`: SET |
101 | | - - set{ "normalized_image_url" } |
102 | | -After processing a page, you delete these ones from redis |
103 | | - |
104 | | -These ones I can save |
105 | | - |
106 | | -These need to be in storage |
107 | | -- `image:<image_url>`: HASH |
108 | | - - 1) "normalized_page_url" - string |
109 | | - - 2) "alt" - string |
110 | | -- `normalized_url:<normalized_page_url>` STRING |
111 | | - - "raw_url" |
112 | | - |
113 | | -These should be saved in storage (Page Rank Algorithm) |
114 | | -- `backlinks:*`: SET |
115 | | - - set{ "normalized_page_url" } |
116 | | -- `outlinks:*`: SET |
117 | | - - set{ "normalized_page_url" } |
118 | | - |
119 | | -These are given by the indexer (Page Rank Algorithm) |
120 | | -- `word:<word>`: ZSET |
121 | | - - set{ "normalized_page_url", SCORE } |
122 | | -- `word_images:<word>` ZSET |
123 | | - - set{ "normalized_image_url", SCORE } |
124 | | - |
125 | | -This is to display results |
126 | | -- `url_metadata:<normalized_page_url>`: hash |
127 | | - - 1) "title" - integer |
128 | | - - 2) "summary_text" - string |
129 | | - - 3) "description" - string |
130 | | - - 4) "normalized_url" - string |
131 | | - - 5) "last_crawled" - timestamp |
132 | | - |
133 | | - |
134 | | - |
135 | | - |
136 | | - // Redis Data: some keys stay in Redis indefinitely, while others are transfer to MongoDB by other services |
137 | | - NormalizedURLPrefix = "normalized_url" // Stays in Redis indefinitely |
138 | | - PagePrefix = "page_data" // Transferred by the indexer |
139 | | - ImagePrefix = "image_data" // Transferred by the image indexer |
140 | | - PageImagesPrefix = "page_images" // Transferred by the image indexer |
141 | | - BacklinksPrefix = "backlinks" // Transferred by the backlinks processor |
142 | | - OutlinksPrefix = "outlinks" // Transferred by the indexer |
| 41 | +## Workflow |
| 42 | + |
| 43 | +1. Spiders crawl and pushes raw content into a Redis queue. |
| 44 | +2. Indexer and Image indexer process the content, updating the search index. |
| 45 | +3. Backlinks processor updates the backlinks data in MongoDB. |
| 46 | +4. TF-IDF calculates the term frequency-inverse document frequency for each term in the indexed pages. |
| 47 | +5. Page Rank calculates the PageRank of each page based on the backlinks data. |
| 48 | +6. Query Engine handles incoming queries and returns ranked results. |
| 49 | +7. Client (frontend) lets users enter queries and view results. |
| 50 | + |
| 51 | +## Tech Stack |
| 52 | +- **Redis** for a fast in-memory data store and message broker. |
| 53 | +- **MongoDB** for a scalable NoSQL database to store indexed data. |
| 54 | +- **Docker** for containerization of services. |
| 55 | +- **Go** for a high performance spider and page rank calculation. |
| 56 | +- **Python** for the indexer, image indexer, backlinks processor, and tf-idf calculation. |
| 57 | +- **PHP** with **Laravel** for the query engine. |
| 58 | +- **HTML/CSS/JS** for the client-side web interface. |
| 59 | + |
| 60 | +## Setup |
| 61 | +- Clone the repository by running `git clone https://github.com/IonelPopJara/moogle`. |
| 62 | +- Install Docker and Docker Compose on your machine. |
| 63 | +- Read each service's README file for specific setup instructions. |
| 64 | +- Follow the instructions in the README files to set up each service. |
0 commit comments