89a97a492f56a3fe2f948c1c6277e245ac911bd5
1 # -*- encoding: utf-8 -*-
2 import simplejson
, re
, datetime
, operator
, hashlib
3 from savoirs
.globals import *
4 from savoirs
.models
import Record
8 Classe permettant de d'encoder et de décoder les données moissonnées.
12 def encode(self
, field
, data
):
13 if field
in META
.keys() and META
[field
]['type'] == 'array':
14 return self
.separator
.join(data
)
18 def decode(self
, field
, data
):
19 if field
in META
.keys() and META
[field
]['type'] == 'array':
20 return data
.split(self
.separator
)
25 # for r in Record.objects.all():
26 # for f in META.keys():
27 # json = getattr(r, f)
28 # if json is not None:
29 # normal = simplejson.loads(json)
30 # new = self.encode(f, normal)
36 Classe utilisée pour réaliser manipuler les données moisonnées.
39 encoder
= SEPEncoder()
41 ############################################################################
43 ############################################################################
46 """Recupérer la structure de métadonnées pour un record selon un `id`."""
47 r
= Record
.objects
.get(id = id)
49 for k
in META
.keys ():
53 meta
[k
] = self
.encoder
.decode(k
, v
)
56 def _save (self
, metadata
):
58 for k
in metadata
.keys ():
59 setattr (r
, k
, self
.encoder
.encode(k
, metadata
[k
]))
60 r
.last_checksum
= hashlib
.md5(str(metadata
)).hexdigest()
61 r
.last_update
= datetime
.datetime
.today()
65 def _modify (self
, id, metadata
):
66 r
= Record
.objects
.get(id = id)
68 # test si le fichier a été modifié
69 if hashlib
.md5(str(metadata
)).hexdigest() == r
.last_checksum
:
72 for k
in metadata
.keys ():
73 setattr (r
, k
, self
.encoder
.encode(k
, metadata
[k
]))
75 r
.last_update
= datetime
.datetime
.today()
79 def _combine (self
, result_lists
, op
):
83 for list in result_lists
:
84 simple_sets
.append (set([x
[0] for x
in list]))
85 for (id, score
) in list:
86 if scores
.get (id) is None:
93 matches
= set(matches
) | s
95 if len (matches
) == 0:
98 matches
= set(matches
) & s
101 return [(x
, scores
[x
]) for x
in matches
]
104 def _text_search (self
, q
, fields
= None):
106 fields
= [x
for x
in META
.keys() if META
[x
].get("text_search", False)]
108 w
= re
.compile (r
'\W+', re
.U
)
113 if len(fields
)==1 and fields
[0] == "subject":
114 suffix
= " IN BOOLEAN MODE"
117 matches
.append ("MATCH(`%s`) AGAINST ('%s'%s)" % (k
, " ".join(words
), suffix
))
118 m
= "+".join (matches
)
120 q
= "SELECT id, (" + m
+ ") AS score FROM savoirs_record WHERE (" \
121 + m
+ ") HAVING score > 0 ORDER BY score DESC"
123 from django
.db
import connection
, transaction
124 cursor
= connection
.cursor()
126 rc
= cursor
.fetchall()
129 ############################################################################
131 ############################################################################
133 def add (self
, metadata
):
134 """Ajouter la ressource définie par `metadata`. Si on trouve une
135 ressource avec le même `identifier`, on le met a jour.
137 Retourne l'id de la ressource créée ou mise à jour.
139 added
= updated
= False
140 exists
= self
.search (q
= {URI
: metadata
[URI
]})
143 updated
= self
.update (int(id), metadata
)
146 id = self
._save (metadata
)
147 return {'record_id': id, 'added':added
, 'updated':updated
}
149 def delete (self
, id):
150 """Supprime la ressource identifiée par `id`.
152 r
= Record
.objects
.get(id = id)
155 def update (self
, id, metadata
):
156 """Met a jour la ressource identifiée par `id`, avec les données de
157 `metadata`. Une exception est levée si elle n'existe pas.
159 if self
.get (int(id)) is not None:
160 return self
._modify (int(id), metadata
)
162 raise Exception ("Objet inexistant")
166 """Recupérer la structure de métadonnées pour la ressource identifiée
167 par `id`. `id` peut être une liste si on veut les structures de
168 plusieurs ressources.
170 if isinstance (id, tuple) or isinstance (id, list):
176 rc
.append (self
._load (int(i
)))
178 rc
= self
._load (int(id))
182 """ Retourner la liste complète des ids des ressources."""
183 return [x
.id for x
in Record
.objects
.all()]
185 def search (self
, q
):
186 """Effectue une recherche multi-critères, en fonction du dictionnaire
187 `q`. Retourne une list d'`id`s uniquement. Les données pour chaque
188 résultat doivent être chargées ulterieurement.
195 ww
= q
.get ("q", "").strip()[1:-1]
197 s
= self
._text_search (ww
)
201 elif q
.get (URI
) is not None:
204 s
.append((Record
.objects
.get(uri__iexact
= q
.get(URI
)).id, 1))
209 creator
= q
.get ("creator", "")[1:-1]
210 title
= q
.get ("title", "")[1:-1]
211 description
= q
.get ("description", "")[1:-1]
212 subject
= q
.get ("subject", "")[1:-1]
214 if len (creator
) > 0:
215 sets
.append (self
._text_search (creator
, [CREATOR
, CONTRIBUTOR
]))
217 sets
.append (self
._text_search (title
, [TITLE
, ALT_TITLE
]))
218 if len (description
) > 0:
219 sets
.append (self
._text_search (description
, [DESCRIPTION
, ABSTRACT
]))
220 if len (subject
) > 0:
221 sets
.append (self
._text_search (subject
, [SUBJECT
,]))
222 rc
= self
._combine (sets
, q
.get ("operator", "|"))
223 rc
.sort (key
= operator
.itemgetter(1), reverse
= True)
226 rc
= [x
[0] for x
in rc
]