مشروع مدرسي من Programming Project 2 ، Group 2 ، Professional Bachelor "Applied It" في ErasmumShogeschool Brussel.
تطبيق محرك البحث لوثائق التأمين. تقوم شركات التأمين بتخزين المستندات حول التشريعات والفقه والعقيدة القانونية في مجالها الخاص. الهدف من ذلك هو تزويد الموظفين بتطبيق محرك بحث سهل الاستخدام استنادًا إلى algorythms في إطار Elasticsearch.
| عنصر | إصدار |
|---|---|
| Linux Ubuntu | |
| fscrawler | |
| Elasticsearch | 6.8 |
| Elasticsearch-php | 6.7 |
| PHP | 7.4.10 (CLI) |
| الملحن | 2.0.6 |
| مثبت Laravel | 4.1.0 |
| MySQL |
ملاحظة: FSCRAWLER VXXXX متوافق فقط مع Elasticsearch 6.8. وبالتالي ، تتطلب حزمة Elasticsearch-PHP V6.7 في ملف Laravel Composer.json الخاص بك
يمكن العثور على الوثائق الكاملة هنا. يتم تخزين المستندات داخل Repo Under /Docs /، لذلك إذا رأيت خطأً أو مشكلة ، فيرجى إرسال PR لإصلاحه!
نحن نقدم أيضًا مولد أمثلة رمز لـ PHP باستخدام البرنامج النصي util/GenerateDocExamples.php . هذا الأمر تحليل ملف util/alternative_report.spec.json الذي تم إنتاجه من مواصفات JSON هذه ويقوم بإنشاء أمثلة PHP foreach distage. يتم تخزين الأمثلة بتنسيق ASCIIDOC في مجلد docs/examples .
الطريقة الموصى بها لتثبيت Elasticsearch-PHP هي من خلال الملحن.
أضف elasticsearch/elasticsearch باعتباره تبعية في ملف composer.json لمشروعك (تغيير الإصدار لتناسب نسختك من Elasticsearch ، على سبيل المثال لـ ES 7.0):
{
"require" : {
"elasticsearch/elasticsearch" : " ^7.0 "
}
}قم بتنزيل وتثبيت الملحن:
curl -s http://getcomposer.org/installer | phpتثبيت تبعياتك:
php composer.phar installتتطلب adoloader الملحن
يقوم الملحن أيضًا بإعداد ملف التحميل التلقائي قادر على التحميل التلقائي لجميع الفصول في أي من المكتبات التي تقوم بتنزيلها. لاستخدامه ، ما عليك سوى إضافة السطر التالي إلى عملية bootstrap الخاصة بكودك:
<?php
use Elasticsearch ClientBuilder ;
require ' vendor/autoload.php ' ;
$ client = ClientBuilder:: create ()-> build ();يمكنك معرفة المزيد حول كيفية تثبيت الملحن ، وتكوين التحميل التلقائي ، وأفضل الممارسات الأخرى لتحديد التبعيات على getComposer.org.
يتطلب الإصدار 7.0 من هذه المكتبة إصدار PHP 7.1 على الأقل. بالإضافة إلى ذلك ، يتطلب أن يكون ملحق JSON الأصلي الإصدار 1.3.7 أو أعلى.
| Elasticsearch-PHP فرع | إصدار PHP |
|---|---|
| 7.0 | > = 7.1.0 |
| 6.0 | > = 7.0.0 |
| 5.0 | > = 5.6.6 |
| 2.0 | > = 5.4.0 |
| 0.4 ، 1.0 | > = 5.3.9 |
نظرًا لأن Insuraquest يستخدم Laravel JetStream ، فإنه يتضمن تسجيل الدخول والتسجيل والتحقق من البريد الإلكتروني والمصادقة ثنائية العوامل وإدارة الجلسة خارج المربع. يستخدم JetStream Laravel Fatify ، وهو الواجهة الخلفية للمصادقة غير الملحمية في الواجهة الأمامية لـ Laravel.
في ملف تكوين config/fatify.php ، يمكنك تخصيص الجوانب المختلفة ، واختر الجوانب التي ترغب في تنفيذها في مشروعك وما إلى ذلك.
يمكن العثور على المنطق المراد تنفيذه بناءً على طلب التفويض ، وتعديله في App Actions Fortify.
يمكن العثور على مزيد من المعلومات والوثائق على JetStream على موقع JetStream.
يقوم Insuraquest بتنفيذ التفويض من خلال السمة "النوع" الذي يتم تضمينه في كل مستخدم. هناك أربعة أنواع: ضيف ، مستخدم ، أمين المكتبة والمشرف. الأنواع مصنوعة متتالية. كل مستوى جديد له أذونات المستوى أقل من + أذونات إضافية.
يتم فرض التفويض على الطرق المختلفة (web.php). على وجهات النظر المختلطة ، يتم تنفيذها أيضًا على مستوى العرض من خلال تنفيذ Laravel @Can و Cannot الأصلي.
يمكن ضبط الأنواع في قاعدة البيانات مباشرة ، أو في "إدارة المستخدم" عند تسجيل الدخول مع AdminAccount.
عندما لا يتم تسجيل الدخول بعد ، سيتم إعادة توجيهه إلى شاشة تسجيل الدخول. افتراضيًا - عندما يتم تسجيل مستخدم جديد - يتم تعيين نوع "ضيف". سيكون قادرًا على رؤية صفحة الأرض والوثائق ، لكن لا يمكنه الاستعلام عن أي مستندات. يمكن للمستخدم الاستعلام عن المستندات وفتحها وإرسالها بالبريد. يمكن لأمين المكتبة تحميل ملفات جديدة وحذف الملفات وتغيير العلامات عليها. يمكن للمشرف عرض جميع المستخدمين ومعلوماتهم وضبط نوعهم.
وصف إعداد النشر.
"external" : {
"properties" : {
"title" : {
"type" : " text "
},
"language" : {
"type" : " keyword "
},
"date_published" : {
"type" : " date "
},
"issuer" : {
"type" : " keyword "
},
"category" : {
"type" : " keyword "
},
"tag" : {
"type" : " keyword "
}
}
}تعتبر أكثر قوة من خادم Laravel المدمج.
server {
listen 80 ;
server_name 10.3.50.7 ;
root /var/www/insuraquest_production/insuraquest/public ;
add_header X-Frame-Options " SAMEORIGIN " ;
add_header X-XSS-Protection " 1; mode=block " ;
add_header X-Content-Type-Options " nosniff " ;
index index.php ;
charset utf-8 ;
location / {
try_files $uri $uri / /index.php ? $query_string ;
}
location = /favicon.ico { access_log off ; log_not_found off ; }
location = /robots.txt { access_log off ; log_not_found off ; }
error_page 404 /index.php ;
location ~ . php$ {
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock ;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name ;
include fastcgi_params ;
}
location ~ / . ( ? ! well-known). * {
deny all ;
}
}php artisan migrate:fresh --seedgit init --bare /home/student/insuraquest/bare_project.init #! /bin/bash
# check out the files
git --work-tree=/var/www/insuraquest_production --git-dir=/home/student/insuraquest/bare_project.git checkout -f
chmod +x /path/to/bare_project.git/hooks/post-receivegit remote add live ' [email protected]:/home/student/insuraquest/bare_project.git '
git push --set-upstream live maincomposer update chgrp -R www-data insuraquest_productionphp artisan storage:linkفي Elasticsearch-PHP ، يتم تكوين كل شيء تقريبًا بواسطة المصفوفات الترابطية. نقطة نهاية الراحة ، المستند والمعلمات الاختيارية - كل شيء عبارة عن صفيف نقابي.
لفهرسة مستند ، نحتاج إلى تحديد ثلاث قطع من المعلومات: الفهرس والمعرف وجسم المستند. يتم ذلك عن طريق بناء مجموعة نقاط من المفاتيح: أزواج القيمة. إن هيئة الطلب هي في حد ذاتها مجموعة نقاطية بالمفتاح: أزواج القيمة المقابلة للبيانات في المستند الخاص بك:
$ params = [
' index ' => ' my_index ' ,
' id ' => ' my_id ' ,
' body ' => [ ' testField ' => ' abc ' ]
];
$ response = $ client -> index ( $ params );
print_r ( $ response );تشير الاستجابة التي تعود إليها إلى أن المستند تم إنشاؤه في الفهرس الذي حددته. الاستجابة عبارة عن مجموعة نقاطية تحتوي على نسخة فكرية من JSON تعود Elasticsearch:
Array
(
[_index] => my_index
[_type] => _doc
[_id] => my_id
[_version] => 1
[result] => created
[_shards] => Array
(
[total] => 1
[successful] => 1
[failed] => 0
)
[_seq_no] => 0
[_primary_term] => 1
)دعنا نحصل على المستند الذي فهرسناه للتو. سيؤدي هذا ببساطة إلى إرجاع المستند:
$ params = [
' index ' => ' my_index ' ,
' id ' => ' my_id '
];
$ response = $ client -> get ( $ params );
print_r ( $ response ); تحتوي الاستجابة على بعض البيانات الوصفية (الفهرس ، الإصدار ، إلخ) بالإضافة إلى حقل _source ، وهو المستند الأصلي الذي أرسلته إلى Elasticsearch.
Array
(
[_index] => my_index
[_type] => _doc
[_id] => my_id
[_version] => 1
[_seq_no] => 0
[_primary_term] => 1
[found] => 1
[_source] => Array
(
[testField] => abc
)
) إذا كنت ترغب في استرداد حقل _source مباشرة ، فهناك طريقة getSource :
$ params = [
' index ' => ' my_index ' ,
' id ' => ' my_id '
];
$ source = $ client -> getSource ( $ params );
print_r ( $ source ); ستكون الاستجابة مجرد قيمة _source :
Array
(
[testField] => abc
)البحث هو السمة المميزة لـ Elasticsearch ، لذلك دعونا نجرى بحثًا. سوف نستخدم استعلام المباراة كإظهار:
$ params = [
' index ' => ' my_index ' ,
' body ' => [
' query ' => [
' match ' => [
' testField ' => ' abc '
]
]
]
];
$ response = $ client -> search ( $ params );
print_r ( $ response ); الاستجابة تختلف قليلاً عن الردود السابقة. نرى بعض البيانات الوصفية ( took ، timed_out ، وما إلى ذلك) ومجموعة تدعى hits . هذا يمثل نتائج البحث الخاصة بك. يوجد داخل hits مجموعة أخرى تدعى hits ، والتي تحتوي على نتائج بحث فردية:
Array
(
[took] => 33
[timed_out] =>
[_shards] => Array
(
[total] => 1
[successful] => 1
[skipped] => 0
[failed] => 0
)
[hits] => Array
(
[total] => Array
(
[value] => 1
[relation] => eq
)
[max_score] => 0.2876821
[hits] => Array
(
[ 0 ] => Array
(
[_index] => my_index
[_type] => _doc
[_id] => my_id
[_score] => 0.2876821
[_source] => Array
(
[testField] => abc
)
)
)
)
)حسنًا ، دعنا نمضي قدمًا ونحذف المستند الذي أضفناه سابقًا:
$ params = [
' index ' => ' my_index ' ,
' id ' => ' my_id '
];
$ response = $ client -> delete ( $ params );
print_r ( $ response ); ستلاحظ أن هذا بناء جملة متطابق لبناء get . الفرق الوحيد هو العملية: delete بدلاً من get . سوف تؤكد الرد على حذف المستند:
Array
(
[_index] => my_index
[_type] => _doc
[_id] => my_id
[_version] => 2
[result] => deleted
[_shards] => Array
(
[total] => 1
[successful] => 1
[failed] => 0
)
[_seq_no] => 1
[_primary_term] => 1
)نظرًا للطبيعة الديناميكية لـ Elasticsearch ، فإن المستند الأول الذي أضفناه تلقائيًا قام ببناء فهرس مع بعض الإعدادات الافتراضية. دعنا نحذف هذا الفهرس لأننا نريد تحديد إعداداتنا الخاصة لاحقًا:
$ deleteParams = [
' index ' => ' my_index '
];
$ response = $ client -> indices ()-> delete ( $ deleteParams );
print_r ( $ response );الرد:
Array
(
[acknowledged] => 1
)الآن بعد أن بدأنا Fresh (بدون بيانات أو فهرس) ، دعنا نضيف فهرسًا جديدًا مع بعض الإعدادات المخصصة:
$ params = [
' index ' => ' my_index ' ,
' body ' => [
' settings ' => [
' number_of_shards ' => 2 ,
' number_of_replicas ' => 0
]
]
];
$ response = $ client -> indices ()-> create ( $ params );
print_r ( $ response );سيقوم Elasticsearch الآن بإنشاء هذا الفهرس مع الإعدادات التي اخترتها ، وإرجاع إقرار:
Array
(
[acknowledged] => 1
) يتمتع أمين المكتبة بإمكانية تحميل ملفات جديدة. عند تحميل مستند ، من الممكن إضافة علامات إلى المستند الذي تم تحميله. يتم سحب محتوى العلامات من جدول MySQL وإضافته إلى النموذج.
FileUploadController.php
$ this ->validate( $ request , [
' title ' => ' required ' ,
' language ' => ' required ' ,
' date ' => ' required|date ' ,
' issuer ' => ' required ' ,
' category ' => ' required ' ,
' tag ' => ' required ' ,
' file ' => ' required|mimes:pdf|max:2048 '
]عند تحميل مستند ، يتم نشر الملف والعلامات على FSCRAWLER ، والتي ستقوم بفهرسة المستند قبل الإضافة إلى عقدة Elasticsearch الخاصة بنا.
FileUploadController.php
$ file = $ request -> file ( ' file ' );
$ pathname = $ file -> store ( ' public ' );
$ fully_qualified_pathname = storage_path ( ' app/ ' . $ pathname );
$ client = new Client ();
try {
$ client -> request ( ' POST ' , ' http://127.0.0.1:8080/fscrawler/_upload ' ,
);
} catch ( GuzzleException $ e ) {
echo $ e ;
} تتم إضافة مكون إضافي لتخطيط النموذج -> tailwind.config.js
https://tainwindcss-custom-forms.netlify.app/
plugins: [
require ( ' @tailwindcss/custom-forms ' ),
] بعد أن يحصل المستخدم على جميع نتائج البحث ، يمكنه عرض المزيد من التفاصيل حول أي من النتائج.
هنا لديه إمكانية تحرير أو حذف أو إرسال PDF المعروضة.
الملفات المعدلة أو المنشأة لوظائف البريد
تستخدم الأوامر الفئة القابلة للبريد القابلة للبريد لارافيل لإنشاء رسائل البريد الإلكتروني.
php artisan make:mail EmailInsuraquest --markdown=Email.insuraEmail
وحدة تحكم البريد ، في الأساس سنحدد المنطق لعرض قائمة المستخدم. تشغيل الأمر لإنشاء وحدة التحكم.
php artisan make:controller MailController
إمكانية اختبار وظيفة البريد الإلكتروني http: // localhost: 8000/send -email -> إرسال بريد إلى mailtrap (الحساب bart)
TODO: قم بتنفيذ وظيفة البريد في نتيجة البحث الواحدة
use GuzzleHttp Ring Client MockHandler ;
use Elasticsearch ClientBuilder ;
// The connection class requires 'body' to be a file stream handle
// Depending on what kind of request you do, you may need to set more values here
$ handler = new MockHandler ([
' status ' => 200 ,
' transfer_stats ' => [
' total_time ' => 100
],
' body ' => fopen ( ' somefile.json ' ),
' effective_url ' => ' localhost '
]);
$ builder = ClientBuilder:: create ();
$ builder -> setHosts ([ ' somehost ' ]);
$ builder -> setHandler ( $ handler );
$ client = $ builder -> build ();
// Do a request and you'll get back the 'body' response aboveكانت تلك مجرد نظرة عامة على العميل وبناء الجملة. إذا كنت على دراية بـ Elasticsearch ، ستلاحظ أن الأساليب تُسمى تمامًا مثل نقاط النهاية الراحة.
ستلاحظ أيضًا أنه تم تكوين العميل بطريقة تسهل اكتشافًا سهلاً عبر IDE. جميع الإجراءات الأساسية متوفرة بموجب كائن $client (الفهرسة ، والبحث ، والحصول ، وما إلى ذلك). تقع إدارة الفهرس والمفهرس ضمن كائنات $client->indices() و $client->cluster() ، على التوالي.
تحقق من بقية الوثائق لمعرفة كيفية عمل العميل بأكمله.
يرجى ملاحظة أن هذا المشروع مخصص للاستخدام في سياق المدرسة. لمزيد من التطوير ، يرجى الاتصال بـ TE
يجوز للمستخدم اختيار الترخيص الذي يرغبون في استخدامه. نظرًا لعدم وجود حزمة تمييزية قابلة للتنفيذ أو توزيع للتمييز بين الترخيص ، يجب على المستخدم توثيق اختيار ترخيصه خارجيًا ، في حالة إعادة توزيع المكتبة. إذا لم يتم اتخاذ خيار صريح ، فإن الافتراض هو أن إعادة التوزيع تطيع قواعد كلا التراخيص.