varias asignaturas de 4to

This commit is contained in:
2026-03-07 22:10:19 +01:00
parent 66274d145a
commit 81f519dca0
2 changed files with 171 additions and 14 deletions

View File

@@ -44,7 +44,7 @@
"autoReveal": false "autoReveal": false
}, },
"icon": "lucide-folder-closed", "icon": "lucide-folder-closed",
"title": "Files" "title": "Explorador de archivos"
} }
}, },
{ {
@@ -78,8 +78,7 @@
} }
], ],
"direction": "horizontal", "direction": "horizontal",
"width": 300, "width": 300
"collapsed": true
}, },
"right": { "right": {
"id": "3ad564d399e497ab", "id": "3ad564d399e497ab",
@@ -172,32 +171,31 @@
}, },
"left-ribbon": { "left-ribbon": {
"hiddenItems": { "hiddenItems": {
"bases:Create new base": false, "switcher:Abrir selector rápido": false,
"switcher:Open quick switcher": false, "graph:Abrir vista gráfica": false,
"graph:Open graph view": false, "canvas:Crear nuevo lienzo": false,
"canvas:Create new canvas": false, "daily-notes:Abrir la nota de hoy": false,
"daily-notes:Open today's daily note": false, "templates:Insertar plantilla": false,
"templates:Insert template": false, "command-palette:Abrir paleta de comandos": false,
"command-palette:Open command palette": false, "bases:Crear nueva base": false,
"table-editor-obsidian:Advanced Tables Toolbar": false, "table-editor-obsidian:Advanced Tables Toolbar": false,
"obsidian-git:Open Git source control": false "obsidian-git:Open Git source control": false
} }
}, },
"active": "f76c0dfd568461ec", "active": "f76c0dfd568461ec",
"lastOpenFiles": [ "lastOpenFiles": [
"CUARTO/PHAE/Teoria_2526.md",
"CUARTO/AII/Teoria_2526.md",
"Pasted image 20260224113246.png", "Pasted image 20260224113246.png",
"Pasted image 20260224112101.png", "Pasted image 20260224112101.png",
"Pasted image 20260224110141.png", "Pasted image 20260224110141.png",
"Pasted image 20260217115003.png", "Pasted image 20260217115003.png",
"CUARTO/PHAE/Teoria_2526.md",
"Pasted image 20260210134109.png", "Pasted image 20260210134109.png",
"Pasted image 20260210131013.png", "Pasted image 20260210131013.png",
"Pasted image 20260210130956.png", "Pasted image 20260210130956.png",
"Pasted image 20260210125017.png", "Pasted image 20260210125017.png",
"CUARTO/AII/Teoria_2526.md",
"Pasted image 20260205135941.png", "Pasted image 20260205135941.png",
"Pasted image 20260205135914.png", "Pasted image 20260205135914.png",
"Pasted image 20260129132034.png",
"CUARTO/AII/Presentacion.md", "CUARTO/AII/Presentacion.md",
"CUARTO/PHAE", "CUARTO/PHAE",
"CUARTO/SSII/Teoria_2526.md", "CUARTO/SSII/Teoria_2526.md",

View File

@@ -170,3 +170,162 @@ Hacemos lo mismo con las queries, representarlas como vectores en el espacio.
No es buena idea puesto que si dos vectores se superponen (porque son el mismo documento) pero tienen distinto módulo va a salir que hay distancia de un documento consigo mismo. No es buena idea puesto que si dos vectores se superponen (porque son el mismo documento) pero tienen distinto módulo va a salir que hay distancia de un documento consigo mismo.
#### <mark style="background: #D2B3FFA6;">Mejor: usar el ángulo</mark> #### <mark style="background: #D2B3FFA6;">Mejor: usar el ángulo</mark>
Para usar el ángulo tenemos que normalizar los vectores volviéndolos unitarios y entonces podemos comparar la proximidad mediante el ángulo entre ellos. Para usar el ángulo tenemos que normalizar los vectores volviéndolos unitarios y entonces podemos comparar la proximidad mediante el ángulo entre ellos.
# <mark style="background: #FFF3A3A6;">Whoosh</mark>
## <mark style="background: #ADCCFFA6;">1. Introducción</mark>
Whoosh sólo funciona con caracteres unicode. El workflow es el mismo siempre:
1. Crear un schema con los tipos de los datos que tendrá el índice
- Con `stored=True` en los tipos, se indica los campos que se almacenarán. Solamente los campos que estén almacenados se mostrarán en `print` o similares.
1. Crear el indexador
2. Crear el writer
3. Añadir documentos al writer (y commit)
### <mark style="background: #FFB86CA6;">Ejemplo de búsqueda</mark>
```python
with ix.searcher() as searcher:
query = QueryParser("content", ix.schema).parse("hola") # contenido a buscar
results = searcher.search(query)
results[0]
```
## <mark style="background: #ADCCFFA6;">2. Diseño del schema</mark>
### <mark style="background: #FFB86CA6;">Tipos</mark>
- **`TEXT`**: por defecto almacena la posición de cada término indexado por si hay que buscar por frases. Si no hace falta buscar por frases, mejor pasarle `phrase=False`.
- **`KEYWORD`**: para keywords separadas por `,` se usa `KEYWORD`. Se puede especificar si está separado por comas con `commas=True` (por defecto está separado por `' '`). También se puede usar `lowercase=True` para convertirlo a minúsculas automáticamente. Por último, `scorable=True` es por si el campo se usará para buscar.
- **`ID`**: se indexan sin dividirse en términos. No vale para el ranking. Se usa para la url, el path, la fecha, etc. Por defecto tienen `stored=False`.
- **`STORED`**: se almacena pero ni se indexa ni se puede buscar en él. Se suele usar para información que se mostrará solamente.
- **`NUMERIC`**: para números
- **`DATETIME`**: para fechas
- **`BOOLEAN`**: para booleanos. Permite buscar por `'yes'`, `'no'`, `'true'`, `'false'`, `1`, `0`, `'t'` o `'f'`.
### <mark style="background: #FFB86CA6;">Creando un schema</mark>
```python
schema = Schema(from_addr=ID(stored=True),
to_addr=ID(stored=True),
subject=TEXT(stored=True),
body=TEXT(analyzer=StemmingAnalyzer()),
tags=KEYWORD)
```
### <mark style="background: #FFB86CA6;">Modificando el schema después de indexar</mark>
```python
writer = ix.writer()
writer.add_field("fieldname", fields.TEXT(stored=True))
writer.remove_field("content")
writer.commit()
```
Con `optimize=True` en el commit, se hace el borrado físico de los datos eliminados con `.remove_field()`.
### <mark style="background: #FFB86CA6;">Campos dinámicos</mark>
Son campos cuyos valores se capturarán mediante regex. Se crean así:
```python
schema.add("*_d", fields.DATETIME(stored=True), glob=True)
```
### <mark style="background: #FFB86CA6;">Dando pesos a los campos para el ranking</mark>
Con el atributo `field_boost` podemos darle más valor a un campo que a otro para la búsqueda rankeada.
## <mark style="background: #ADCCFFA6;">3. Indexando documentos</mark>
Para crear un índice usamos:
```python
ix = index.create_in("indexdir", schema)
```
Y para buscar en uno ya creado:
```python
ix = index.open_dir("indexdir")
```
Para añadir documentos al índice ya creado, se crea un writer y se añaden documentos.
```python
writer.add_document(title=u"Title to be indexed", _stored_title=u"Stored title")
```
En realidad, un índice creado por `filedb` es un contenedor de varios subíndices llamados segmentos. Para borrar documentos se puede borrar de varias formas:
```python
delete_by_term(fieldname, termtext)
delete_by_query(query)
```
Para actualizar documentos es obligatorio que haya un campo `unique=True`, **aunque esto no hace que no se pueda repetir (no tiene que ver con las KEY de BBDD relacionales)**. La función para actualizar:
```python
writer.update_document(path=u"/a", content="Replacement for the first document")
```
## <mark style="background: #ADCCFFA6;">4. Buscando en el índice</mark>
Se usa un objeto Searcher para buscar:
```python
qp = QueryParser("content", schema=myindex.schema)
q = qp.parse(u"hello world")
with myindex.searcher() as s:
results = s.search(q)
```
Se le puede poner `limit` a la query para que de mas de los 10 resultados rankeados por defecto que devuelve. Con `limit=None` devuelve todos.
### <mark style="background: #FFB86CA6;">Objeto Results</mark>
Es una lista de dicts. Tiene varias funciones para ver el número de resultados sin rankear o rankeados.
```python
found = results.scored_length()
if results.has_exact_length():
print("Scored", found, "of exactly", len(results), "documents")
else:
low = results.estimated_min_length()
high = results.estimated_length()
print("Scored", found, "of between", low, "and", high, "documents")
```
### <mark style="background: #FFB86CA6;">Algoritmos de ranking</mark>
```python
with myindex.searcher(weighting=scoring.TF_IDF()) as s:
...
```
### <mark style="background: #FFB86CA6;">Filtrando</mark>
```python
with myindex.searcher() as s:
qp = qparser.QueryParser("content", myindex.schema)
user_q = qp.parse(query_string)
# Only show documents in the "rendering" chapter
allow_q = query.Term("chapter", "rendering")
# Don't show any documents where the "tag" field contains "todo"
restrict_q = query.Term("tag", "todo")
results = s.search(user_q, filter=allow_q, mask=restrict_q)
```
## <mark style="background: #ADCCFFA6;">5. Parseando queries</mark>
- En las queries se pueden usar operadores como `AND` o `OR`. Por defecto es `AND`, pero si queremos que sean `OR` sin ponerlos, se puede hacer así:
```python
parser = qparser.QueryParser(fieldname, schema=myindex.schema,
group=qparser.OrGroup)
```
- Para buscar en varios campos:
```python
mparser = MultifieldParser(["title", "content"], schema=myschema)
```
- Para buscar frases se debe poner la query entre `""`.
- También se puede usar `~X` para ver si una palabra está `X` palabras después (`whoosh library~5`).
- Si no se pone `campo:valor` buscará siempre en el campo por defecto.
- Para términos inexactos se usan patrones que usan `?` para un sólo caracter y `*` para varios (**se aplican solo a palabras no a frases**).
- Para rangos, se usa `TO`. Se pueden usar también para fechas (formato por defecto: YYYYMMDD).
```
date:[20050101 TO 20090715]
[0000 TO 0025}
{prefix TO suffix}
[0025 TO]
{TO suffix}
```
- Se puede especificar el peso de la palabra independientemente del campo en el que aparezca con `^X` donde `X` es el peso.
## <mark style="background: #ADCCFFA6;">6. Otros formatos de fecha</mark>
Con el `DateParserPlugin` (que se añade al QueryParser con `.add_plugin(DateParserPlugin())`) se puede buscar por varias cosas:
```
20050912
2005 sept 12th
june 23 1978
23 mar 2005
july 1985
sep 12
today
yesterday
tomorrow
now
next friday
last tuesday
5am
10:25:54
23:12
8 PM
4:46 am oct 31 2010
last tuesday to today
today to next friday
jan 2005 to feb 2008
-1 week to now
now to +2h
-1y6mo to +2 yrs 23d
```