diff --git a/Ela_Spacy.py b/Ela_Spacy.py index 9316014..49bbad6 100644 --- a/Ela_Spacy.py +++ b/Ela_Spacy.py @@ -458,3 +458,95 @@ def test_ela_myntlk(): my_file.close() ''' +def ela_index_article_avis_record_field(lines, article_avis_id, source_field = ""): + + try: + ''' + ## Suppression de toutes les indexation qui existe de cette formation + ''' + client = MongoClient(CONNECTION_STRING) + dbname = client['cherifdb'] + coll_name = dbname['elaindex_article_avis'] + + # check default value of parameter : source_field + if len(str(source_field)) == 0 : + source_field = 'default' + + myquery = {"id_articles_avis": article_avis_id, "source_field":source_field} + delete_row = coll_name.delete_many(myquery) + mycommon.myprint(" elaindex Article AVIS : - "+str(delete_row.deleted_count)+" documents deleted. Article_Avis ==> "+str(article_avis_id)+" ") + + ''' + Ajout des indexe + ''' + tab_tokens = Ela_Tokenize(lines) + tab_tokens2 = Ela_remove_stop_words(tab_tokens) + tab_tokens3 = Ela_remove_pronoun(tab_tokens2) + tab_tokens4 = Ela_stemmize(tab_tokens3) + + tab_tokens4 = Ela_Remove_Noise_from_list(tab_tokens4) + tab_tokens4 = Ela_remove_ponct(tab_tokens4) + + # Enregistrement dans la base mongodb + + Ela_article_avis_list_to_mongo(tab_tokens4, article_avis_id, source_field) + + size_tab = len(tab_tokens4) + + occurrences = Counter(tab_tokens4) + most_common = occurrences.most_common() + print(most_common) + + return True + except Exception as e: + exc_type, exc_obj, exc_tb = sys.exc_info() + mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno)) + return False + + +def Ela_article_avis_list_to_mongo(tab_tokens, traning_id, source_field): + try: + # clear / truncate elaindex + #db.elaindex.remove({}) + + # Recherche des occurence d'une valeur + my_file = open("ela_output_article_file_pandas_2.txt", "w") + size_tab = len(tab_tokens) + + occurrences = Counter(tab_tokens) + + # insert the list to the set + list_set = set(tab_tokens) + # convert the set to the list + unique_list = (list(list_set)) + + final_lists = [] + for tmp in unique_list: + moyenne = round(int(occurrences[str(tmp)]) / size_tab, 2) + final_lists.append([str(tmp), int(str(occurrences[str(tmp)])), str(moyenne), str(traning_id), str(source_field)]) + + print(final_lists) + data = pd.DataFrame(final_lists, columns=('mots', "occurence", 'moyenne', 'id_article_avis', 'source_field')) + my_file.write(str(data)) + my_file.close() + + # Making a Connection with MongoClient + client = MongoClient("mongodb://localhost:27017/") + # database + db = client["cherifdb"] + # collection + collection = db["elaindex_article_avis"] + + data.reset_index(inplace=True) + data_dict = data.to_dict("records") + + # Insert collection + collection.insert_many(data_dict) + data.to_csv("data_indexees_article_avis.csv") + + return True + except Exception as e : + exc_type, exc_obj, exc_tb = sys.exc_info() + mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno)) + return False + diff --git a/articles_avis.py b/articles_avis.py index 110c7dd..897327e 100644 --- a/articles_avis.py +++ b/articles_avis.py @@ -280,7 +280,6 @@ def add_articles_avis(diction): my_user_recid = user_recid - print(" ########### RECID = "+user_recid) mydata['user_recid'] = my_user_recid mydata['token'] = my_token @@ -373,4 +372,253 @@ def add_articles_avis(diction): except Exception as e: exc_type, exc_obj, exc_tb = sys.exc_info() mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno)) - return False, " Impossible de créer l'article/avis" \ No newline at end of file + return False, " Impossible de créer l'article/avis" + + +''' +Cette fonction recherche un aricles ou avis +''' +def recherche_articles_avis(diction): + try: + + ''' + # Verification que les champs reçus dans l'API sont bien dans la liste des champs autorisés + # Cela evite le cas ou une entité tierce ajouter les valeurs inconnu dans l'API + # Ici on doit mettre tous les champs possible (obligatoire ou non) de la BDD dans la liste + # field_list. + ''' + field_list = ['token', 'user_ip', 'user_country_code', 'user_country_name', 'user_city', + 'user_postal', 'user_latitude', 'user_longitude', 'user_state', 'search_text'] + incom_keys = diction.keys() + for val in incom_keys: + if val not in field_list: + mycommon.myprint( + str(inspect.stack()[0][3]) + " - : Le champ '" + val + "' n'existe pas, recherche annuléee") + return False, " Le champ '" + val + "' n'existe pas, recherche annulée" + + ''' + Une fois qu'on a controlé que toutes les clés mise dans l'API sont correcte. etape precedente, + On controle que les champs obligatoires sont presents dans la liste + ''' + field_list_obligatoire = ['search_text', 'token'] + + for val in field_list_obligatoire: + if val not in diction: + mycommon.myprint( + str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans liste ") + return False, " : La valeur '" + val + "' n'est pas presente dans liste " + + # recuperation des paramettre + search_text = "" + user_recid = "" + token = "" + if ("search_text" in diction.keys()): + if diction['search_text']: + search_text = diction['search_text'] + + + if ("token" in diction.keys()): + if diction['token']: + token = diction['token'] + + # Verification de la validité du token/mail dans le cas des user en mode connecté + if (len(str(token)) > 0): + retval = mycommon.check_token_validity("", token) + + if retval is False: + mycommon.myprint(str(inspect.stack()[0][3]) + " - Le token n'est pas valide") + return False, "Le token n'est pas valide" + + # Recuperation du recid de l'utilisateur + user_recid = mycommon.get_user_recid_from_token(token) + if user_recid is False: + mycommon.myprint( + str(inspect.stack()[0][3]) + " - Impossible de recuperer le token de l'utilisateur") + return False, " Impossible de desactiver l'objectif utilisateur" + + mycommon.myprint(" On recehrche la phrase +'" + search_text + "' + user_recid = " + user_recid) + # Enregistrerment de la recherche + retval, message, store_recherche_Id = store_recherche_article_avis(diction, user_recid) + if (retval is False): + return retval, message + + tab_training = [] + tab_training = ela_index.ela_recherche_article_avis_tokens(search_text) + mycommon.myprint(" pour phrase : #" + search_text + "#, voici la liste des formations") + mycommon.myprint(tab_training) + + coll_name = dbname['articles_avis'] + + ''' + la valeur nb_result permettra de savoir si la requete a donnée un resultat. + si ce n'est pas le cas, il faudra à la fin enregistrer la requete avec un result a vide''' + nb_result = 0 + insertObject = [] + + for val in tab_training: + + for x in coll_name.find({"title_formation": str(val)}, + {"_id": 0, "indexed": 0, "valide": 0, "locked": 0, }): + nb_result = nb_result + 1 + my_recid = {} + my_recid['user_rec_id'] = str(user_recid) + mydict_combined = {**diction, **x, **my_recid} + mydict_combined['date_update'] = str(datetime.now()) + mydict_combined['type_view'] = "summary" + + if ("_id" in mydict_combined.keys()): + mydict_combined['class_id'] = mydict_combined.pop('_id') + + user = x + + + val = x['qualite'] + if (len(x['qualite']) > MAX_CARACT): + x['qualite'] = val[:MAX_CARACT] + " ..." + + else: + x['qualite'] = val[:MAX_CARACT] + + val = x['avis'] + if (len(x['avis']) > MAX_CARACT): + x['avis'] = val[:MAX_CARACT] + " ..." + + else: + x['avis'] = val[:MAX_CARACT] + + + insertObject.append(JSONEncoder().encode(user)) + + return True, insertObject + + + except Exception as e: + exc_type, exc_obj, exc_tb = sys.exc_info() + mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno)) + return False, " Impossible de recherche un article/avis" + +''' +Stockage des recherches sur les avis +''' +def store_recherche_article_avis(diction, user_recid=""): + try: + ''' + # Verification que les champs reçus dans l'API sont bien dans la liste des champs autorisés + # Cela evite le cas ou une entité tierce ajouter les valeurs inconnu dans l'API + # Ici on doit mettre tous les champs possible (obligatoire ou non) de la BDD dans la liste + # field_list. + ''' + + if ( len(str(user_recid)) <= 0 ): + user_recid = 'None' # by default + + + + field_list = ['token', 'user_ip', 'user_country_code', 'user_country_name', 'user_city', + 'user_postal', 'user_latitude', 'user_longitude', 'user_state', 'search_text', 'certif', + 'support', 'type', 'lang', 'price', 'distance', 'duration'] + incom_keys = diction.keys() + for val in incom_keys: + if val not in field_list: + mycommon.myprint(str(inspect.stack()[0][3]) + " Le champ '" + val + "' n'existe pas, recherche annulée") + return False, " Le champ '" + val + "' n'existe pas, recherche annulée", None + + ''' + Une fois qu'on a controlé que toutes les clés mise dans l'API sont correcte. etape precedente, + On controle que les champs obligatoires sont presents dans la liste + ''' + field_list_obligatoire = ['search_text', 'token'] + + for val in field_list_obligatoire: + if val not in diction: + mycommon.myprint(" : La valeur '" + val + "' n'est pas presente dans liste ") + return False, " : La valeur '" + val + "' n'est pas presente dans liste ", None + + + # recuperation des paramettre + mydata = {} + mydata_id = "" + my_token = "" + + if ("search_text" in diction.keys()): + if diction['search_text']: + mydata['search_text'] = diction['search_text'] + + + if ("user_mail" in diction.keys()): + if diction['user_recid']: + mydata['user_recid'] = diction['user_recid'] + + if ("token" in diction.keys()): + if diction['token']: + my_token = diction['token'] + + '''# Recuperation du recid de l'utilisateur + user_recid = mycommon.get_user_recid_from_token(my_token) + if user_recid is False: + mycommon.myprint(" Impossible d'enregistrer la recherche de utilisateur") + return False, " Impossible d'enregistrer la recherche de utilisateur" + ''' + mydata['user_recid'] = user_recid + mydata['document_recherche'] = "articles_avis" + + if ("source" in diction.keys()): + if diction['source']: + mydata['source'] = diction['source'] + + if ("name" in diction.keys()): + if diction['name']: + mydata['name'] = diction['name'] + + + if ("id" in diction.keys()): + if diction['id']: + mydata_id = diction['id'] + + mydata['date_update'] = str(datetime.now()) + + mydata['valide'] = "1" # By default + if ("valide" in diction.keys()): + if diction['valide']: + mydata['valide'] = diction['valide'] + + + coll_name = dbname['user_recherche'] + + # Si le champ "id" est renseigné, il s'agit d'une mis jour + mycommon.myprint(str(inspect.stack()[0][3]) + " on va stocker "+str(mydata)+" id = "+str(mydata_id)) + + if( len(str(mydata_id)) > 0 ): + ret_val = coll_name.find_one_and_update({'_id': ObjectId(str(mydata_id)), 'valide': '1'}, + {"$set": mydata}, + return_document=ReturnDocument.AFTER + ) + + if (ret_val and ret_val['_id']): + nb_doc = str(ret_val['_id']) + mycommon.myprint(str(inspect.stack()[0][3]) + " La recherche a bien été mise à jour . Le Doc Id = "+str(nb_doc)) + return True, "La recherche a bien été mise à jour", ret_val['_id'] + + else: + return False, "Impossible de mettre à jour a la recherche", None + + else: + ret_val = coll_name.insert_one(mydata) + + if ret_val and ret_val.inserted_id: + nb_doc = ret_val.inserted_id + mycommon.myprint(str(inspect.stack()[0][3]) + " La recherche a été bien enregistrée. Id = '" + str(nb_doc)+"' ") + return True, "La recherche a bien été mise à jour", nb_doc + else: + mycommon.myprint( + str(inspect.stack()[0][3]) + "Impossible d'enregistrer la recherche") + return False, "Impossible d'enregistrer la recherche ", None + + + except Exception as e: + exc_type, exc_obj, exc_tb = sys.exc_info() + mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno)) + return False, "Impossible d'enregistrer la recherche", None + + + diff --git a/data_indexees.csv b/data_indexees.csv index bbdeb37..7e8ebb4 100644 --- a/data_indexees.csv +++ b/data_indexees.csv @@ -1,3 +1,2 @@ ,index,mots,occurence,moyenne,id_formation,source_field -0,0,mot,2,0.33,AUTO_CH03,default -1,1,recherch,4,0.67,AUTO_CH03,default +0,0,formation4,0,0.0,formation4,default diff --git a/ela_index_bdd_classes.py b/ela_index_bdd_classes.py index 7ad38a5..be1129f 100644 --- a/ela_index_bdd_classes.py +++ b/ela_index_bdd_classes.py @@ -168,7 +168,6 @@ def ela_index_class(external_code="", source_field = ""): La fonction "ela_index_all_classes" va aller chercher chaque cours dans la BDD et créer les mots clées qui sont ensuite enregister dans la table "elaindex" ''' - def ela_index_all_classes(): # Making a Connection with MongoClient try: @@ -531,3 +530,153 @@ def ela_recherche_tokens_source_field(sentence, source_fied=""): return tab_training_id +'''' +Cette fonction indexe les articles et avis. +important : se ra indexé que le titre de la formation. +apres avoir été indexés la champs "indexed" passe à 1 +''' +def ela_index_all_articles_avis(): +# Making a Connection with MongoClient + try: + # collection + collection = db["articles_avis"] + nb_class_indexed = 0 + for doc in collection.find({'indexed': '0'}): + if ("title_formation" in doc.keys()): + chaine = doc["title_formation"] + mycommon.myprint(" Debut indexation de l'article : "+chaine) + retval = ela_index_articles_avis(str(doc["title_formation"])) + print(" apres : ela_index_class retval = " + str(retval)) + + if (retval is False): + mycommon.myprint("IMPOSSIBLE d'indexer la formation = " + str(doc["external_code"])) + else: + nb_class_indexed = nb_class_indexed + 1 + + # retval = ls.ela_index_record_field(chaine, str(doc["external_code"])) + + mycommon.myprint(str(nb_class_indexed) + " ont été indexes") + + + + return True, str(nb_class_indexed) + " articles ont été indexes " + + except Exception as e: + exc_type, exc_obj, exc_tb = sys.exc_info() + mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno)) + return False, "Impossible d'indexer les articles et avis ==> KO" + + +''' +Cette fonction indexe un article / avis +Par defaut sont pris en compte : +- le titre de la formation +''' +def ela_index_articles_avis(titre_formation="", source_field = ""): + try: + + collection = db["articles_avis"] + + if( len(str(source_field)) == 0): + source_field = 'default' + + for doc in collection.find({"title_formation":titre_formation, "valide":"1"}): + + # Indexation par defaut : champs TITRE FORMATION + if ( str(source_field) == "default" ): + chaine = doc["title_formation"] + #mycommon.myprint(" external_code = "+str(doc["external_code"])+" ==> "+str(chaine)) + retval = ls.ela_index_article_avis_record_field(chaine, str(doc["title_formation"]), source_field) + + ''' + # Apres indexation, on met a jour la formation pour + # mettre le champ "indexe" a 1. + ''' + if( retval ): + # mise à jour du champ "indexed" + myobjectif = {} + myobjectif['indexed'] = '1' + + ret_val2 = collection.find_and_modify(query={"title_formation":titre_formation, "valide":"1"}, + update={"$set": myobjectif} + ) + + if (ret_val2 and ret_val2['_id']): + mycommon.myprint("L'article indexé (champs par defaut) =" + str(ret_val2['_id'])) + return True + else: + return False + + + return True + except Exception as e: + exc_type, exc_obj, exc_tb = sys.exc_info() + mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno)) + return False + + +''' +Cette fonction recherche une chaine de caractère +dans la table des articles et avis. + +Elle retourne le title de la formation +''' + + +def ela_recherche_article_avis_tokens(sentence): + tab_training_id = [] + tab_tokens = ls.Ela_Tokenize(sentence) + tab_tokens2 = ls.Ela_remove_stop_words(tab_tokens) + tab_tokens3 = ls.Ela_remove_pronoun(tab_tokens2) + ''' + note : 26/03 : Faire evolution la fonction ici pour + gerer les mots qui ne doivent pas etre racinisé comme le cas du mot "Responsive" + + De manière plus globale, il faudrait exclure certains mot de la racinisation. + + ''' + print(" VERIF : " + str(tab_tokens3)) + tab_corrected_word = [] + for mot in tab_tokens3: + mycommon.recherche_check_word_in_fr_dict(str(mot)) + val = ls.correct_fr_word(str(mot)) + if (val): + tab_corrected_word.append(str(val)) + + print("corrected word = " + str(tab_corrected_word)) + + tab_tokens4 = ls.Ela_stemmize(tab_corrected_word) + + print(" VERIF APRES STEMISATION : " + str(tab_tokens4)) + + tab_tokens4.sort() + + ''' + tab_tokens4 contient la liste des mots à rechercher. + En suite pour chaque mot de "tab_tokens4" on regarde dans la table "elaindex" + a quoi cela pourrait correspondre. + ''' + + # collection + collection = db["elaindex_article_avis"] + + print(" mot recherché tab_tokens4 = " + str(tab_tokens4)) + + pipe2 = [{'$match': {'mots': {'$in': tab_tokens4}}}, + {'$group': { + '_id': "$id_article_avis", + 'count_class': {'$sum': 1}, + 'sum_occurence': {'$sum': '$occurence'} + } + }, + {'$sort': {'count_class': -1, 'sum_occurence': -1}} + ] + + for result in collection.aggregate(pipe2): + tab_training_id.append(str(result["_id"])) + # print(result) + + print("resultat tab_training_id = " + str(tab_training_id)) + + return tab_training_id + diff --git a/ela_output_test_file_pandas_2.txt b/ela_output_test_file_pandas_2.txt index 1b099f3..1316fd7 100644 --- a/ela_output_test_file_pandas_2.txt +++ b/ela_output_test_file_pandas_2.txt @@ -1,3 +1,2 @@ - mots occurence moyenne id_formation source_field -0 mot 2 0.33 AUTO_CH03 default -1 recherch 4 0.67 AUTO_CH03 default \ No newline at end of file + mots occurence moyenne id_formation source_field +0 formation4 0 0.0 formation4 default \ No newline at end of file diff --git a/main.py b/main.py index 6052a41..fffecef 100644 --- a/main.py +++ b/main.py @@ -878,6 +878,33 @@ def add_articles_avis(): return jsonify(status=status, message=retval) +''' +Cette API indexe les articles et avis postés +''' + +@app.route('/myclass/api/ela_index_all_articles_avis/', methods=['POST','GET']) +@crossdomain(origin='*') +def ela_index_all_articles_avis(): + # On recupere le corps (payload) de la requete + payload = request.form.to_dict() + print(" ### payload = ",payload) + status, retval = ela_index_class.ela_index_all_articles_avis() + return jsonify(status=status, message=retval) + + +''' +Cette API recherche un articles ou un avis en se basant sur le +titre de la formation''' +@app.route('/myclass/api/recherche_articles_avis/', methods=['GET','POST']) +@crossdomain(origin='*') +def recherche_articles_avis(): + # On recupere le corps (payload) de la requete + payload = request.form.to_dict() + print(" ### payload = ", payload) + status, result = aa.recherche_articles_avis(payload) + return jsonify(status=status, message=result) + + if __name__ == '__main__': print(" debut api") diff --git a/wrapper.py b/wrapper.py index e1c73dc..0d59aa4 100644 --- a/wrapper.py +++ b/wrapper.py @@ -503,10 +503,7 @@ def recherche_text_simple(diction): coll_name = dbname['myclass'] - print(" Dans la recherch, les critère = "+str(certif_crit)+" la langue = "+str(lang_crit)+ - " price = "+str(price_crit)+" Duration = "+str(duration_crit)) - #ici ajouter tous les critère comme ci-dessous avec le support et le certif ''' la valeur nb_result permettra de savoir si la requete a donnée un resultat. si ce n'est pas le cas, il faudra à la fin enregistrer la requete avec un result a vide''' @@ -529,7 +526,6 @@ def recherche_text_simple(diction): if ("_id" in mydict_combined.keys()): mydict_combined['class_id'] = mydict_combined.pop('_id') - #mycommon.myprint("COMBINED = " + str(mydict_combined)) ''' Statistique : Insertion du recherche - resultat ''' @@ -662,6 +658,7 @@ def store_recherche(diction, user_recid=""): return False, " Impossible d'enregistrer la recherche de utilisateur" ''' mydata['user_recid'] = user_recid + mydata['document_recherche'] = "formation" if ("type" in diction.keys()): if diction['type']: