Browse Source

implemented new filter for tags when requesting list of events:

until now, filtering was done _after_ reading events from the db.
Now we first search viable appointment ids when tags are set and add these to the where clause for the actual request

Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
main
Stephan Richter 4 months ago
parent
commit
fa8b5f2c57
  1. 3
      de.srsoftware.cal.db/src/main/java/de/srsoftware/cal/db/Database.java
  2. 48
      de.srsoftware.cal.db/src/main/java/de/srsoftware/cal/db/MariaDB.java
  3. 2
      de.srsoftware.cal.web/src/main/java/de/srsoftware/cal/ApiEndpoint.java

3
de.srsoftware.cal.db/src/main/java/de/srsoftware/cal/db/Database.java

@ -4,6 +4,7 @@ package de.srsoftware.cal.db; @@ -4,6 +4,7 @@ package de.srsoftware.cal.db;
import de.srsoftware.cal.api.Appointment;
import de.srsoftware.tools.Result;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;
import java.util.Set;
@ -28,7 +29,7 @@ public interface Database { @@ -28,7 +29,7 @@ public interface Database {
* @param till restrict appointments to times before this date time
* @return list of appointments in this time span
*/
Result<List<Appointment>> list(LocalDateTime from, LocalDateTime till, Integer count, Integer offset);
Result<List<Appointment>> list(LocalDateTime from, LocalDateTime till, Integer count, Integer offset, Collection<String> tags);
/**
* list appointments

48
de.srsoftware.cal.db/src/main/java/de/srsoftware/cal/db/MariaDB.java

@ -26,13 +26,18 @@ import java.time.LocalDateTime; @@ -26,13 +26,18 @@ import java.time.LocalDateTime;
import java.util.*;
public class MariaDB implements Database {
private static final System.Logger LOG = System.getLogger(MariaDB.class.getSimpleName());
private static final String APPOINTMENTS = "appointments";
private static final String APPOINTMENT_TAGS = "appointment_tags";
private static final String APPOINTMENT_URLS = "appointment_urls";
private static final String URLS = "urls";
private static final String APPOINTMENT_ATTACHMENTS = "appointment_attachments";
private static final String TAGS = "tags";
private static final System.Logger LOG = System.getLogger(MariaDB.class.getSimpleName());
private static final String APPOINTMENTS = "appointments";
private static final String APPOINTMENT_ATTACHMENTS = "appointment_attachments";
private static final String APPOINTMENT_TAGS = "appointment_tags";
private static final String APPOINTMENT_URLS = "appointment_urls";
private static final String CONFIG = "config";
private static final Object DB_VERSION = "dbversion";
private static final String KEYNAME = "keyname";
private static final String TAGS = "tags";
private static final String TAG_SEARCH = "tag_search";
private static final String URLS = "urls";
private static final String VALUE = "value";
private Connection connection;
private MariaDB(Connection conn) throws SQLException {
@ -42,15 +47,17 @@ public class MariaDB implements Database { @@ -42,15 +47,17 @@ public class MariaDB implements Database {
private void applyUpdates() throws SQLException {
LOG.log(INFO, "Checking for updates…");
var rs = select("value").from("config").where("keyname", equal("dbversion")).exec(connection);
var rs = select(VALUE).from(CONFIG).where(KEYNAME, equal(DB_VERSION)).exec(connection);
var version = 0;
if (rs.next()) {
version = rs.getInt("value");
version = rs.getInt(VALUE);
}
rs.close();
switch (version) {
case 0:
createTables();
case 1:
createTagSearch();
}
}
@ -58,6 +65,11 @@ public class MariaDB implements Database { @@ -58,6 +65,11 @@ public class MariaDB implements Database {
throw new RuntimeException("%s.createTables() not implemented!");
}
private void createTagSearch() throws SQLException {
connection.prepareStatement("CREATE VIEW tag_search AS SELECT aid, GROUP_CONCAT(keyword) AS tags FROM appointment_tags LEFT JOIN tags ON appointment_tags.tid = tags.tid GROUP BY aid").execute();
Query.update(CONFIG).set(VALUE).where(KEYNAME,equal(DB_VERSION)).prepare(connection).apply(2);
}
@Override
public Result<Appointment> add(Appointment appointment) {
try {
@ -162,13 +174,28 @@ public class MariaDB implements Database { @@ -162,13 +174,28 @@ public class MariaDB implements Database {
}
@Override
public Result<List<Appointment>> list(LocalDateTime from, LocalDateTime till, Integer count, Integer offset) {
public Result<List<Appointment>> list(LocalDateTime from, LocalDateTime till, Integer count, Integer offset, Collection<String> tags) {
List<Long> aids = null;
if (tags != null && !tags.isEmpty()){
var query = select(AID).from(TAG_SEARCH);
for (var tag : tags) query.where(TAGS,like("%"+tag+"%"));
try {
var rs = query.exec(connection);
aids = new ArrayList<>();
while (rs.next()) aids.add(rs.getLong(AID));
rs.close();
} catch (SQLException e) {
return SqlError.of(e,"Failed to read appointment ids for tags %s",tags);
}
}
var query = select("appointments.*", "GROUP_CONCAT(keyword) AS tags")
.from(APPOINTMENTS)
.leftJoin(AID, "appointment_tags", AID)
.leftJoin("tid", "tags", "tid")
.groupBy(AID)
.sort("start ASC");
if (aids != null && !aids.isEmpty()) query.where(APPOINTMENTS+"."+AID,in(aids.toArray()));
if (from != null) query.where(START, moreThan(Timestamp.valueOf(from)));
if (till != null) query.where(END, lessThan(Timestamp.valueOf(till)));
if (count != null) query.limit(count);
@ -186,6 +213,7 @@ public class MariaDB implements Database { @@ -186,6 +213,7 @@ public class MariaDB implements Database {
}
private void addAttachments(ArrayList<Appointment> list) {
if (list.isEmpty()) return;
var map = new HashMap<Long,BaseAppointment>();
list.stream().filter(app -> app instanceof BaseAppointment)

2
de.srsoftware.cal.web/src/main/java/de/srsoftware/cal/ApiEndpoint.java

@ -150,7 +150,7 @@ public class ApiEndpoint extends PathHandler { @@ -150,7 +150,7 @@ public class ApiEndpoint extends PathHandler {
Result<LocalDateTime> end = parseDate(param.get(END));
var endDate = (end == null) ? null: end.optional().orElse(null);
return db.list(startDate, endDate, count, offset).map(res -> filterByTags(res, tags));
return db.list(startDate, endDate, count, offset, tags).map(res -> filterByTags(res, tags));
}
private Result<List<Appointment>> filterByTags(Result<List<Appointment>> res, List<String> tags) {

Loading…
Cancel
Save