Knex: Unterstützung für Volltextsuchindizes

Erstellt am 15. März 2014  ·  36Kommentare  ·  Quelle: knex/knex

Postgres, SQLite und MySQL unterstützen alle eine Form von Volltextindex. Es wäre nützlich, das Generieren von Schemas und das Abfragen basierend auf diesen Indizes zu unterstützen.

Dies scheint keine triviale Funktion zu sein, da die Implementierungen hinsichtlich der Anforderungen für die Indexerstellung (SQLite scheint sich auf Tabellenebene zu befinden, MySQL unterstützt es nur für MyISAM-Tabellen) und Abfragen sehr unterschiedlich sind.

Dieses Problem könnte jedoch zumindest dazu verwendet werden, das Interesse an einer solchen Funktion zu verfolgen.

Verweise:

Beispiel für die Erstellung und Abfrage von Indizes:

  • PostgreSQL:
CREATE INDEX <INDEX NAME> ON <TABLE NAME> USING gin(to_tsvector(<COLUMN NAME>));

SELECT * FROM <TABLE NAME> WHERE <COLUMN NAME> @@ to_tsquery(<INPUT>);
  • MySQL:
CREATE FULLTEXT INDEX <INDEX NAME> ON <TABLE NAME>;

SELECT * FROM <TABLE NAME> WHERE MATCH <COLLUMN NAME> AGAINST <INPUT>;
  • SQLite:
CREATE VIRTUAL TABLE <TABLE> USING fts3(<COLUMN NAME> TEXT);

SELECT * FROM <TABLE NAME> WHERE <COLUMN NAME> MATCH <INPUT>;
feature request help wanted

Hilfreichster Kommentar

Kommentare zu Flut +1 und Statusaktualisierungsanforderung entfernt. Bitte verwenden Sie die Daumen für die Abstimmung

BEARBEITEN: Wenn dieser Feed keine neuen Nachrichten enthält, gibt es nichts Neues zu erzählen

Alle 36 Kommentare

Natürlich unterstützt, dachte ich, es könnte bereits unterstützt worden sein, da es irgendwie wichtig erscheint.

Wird in der nächsten Nebenversion unterstützt, dafür fotografiere ich Ende März.

@tgriesser wow, das ist unerwartet aber genial. Dankeschön!

@tgriesser Ist das tatsächlich passiert?

Es ist noch nicht veröffentlicht. Lassen Sie mich trotzdem gehen und sicherstellen, dass dies hinzugefügt wurde, und versuchen, fast jedes verbleibende Ticket hier mit der neuen Version zu schließen. Ich weiß, dass Sie jetzt die Spalte umbenennen und die Typen ändern können :)

Oooooooh aufregend! : tada: cc / @sebgie

@ErisDS, also t.text('colName').fulltext() oder t.fulltext(columnName) tun .. Ich wollte nur sicherstellen, dass Sie sich darüber im Klaren sind, dass Sie in sqlite3 nicht mehr in der Lage sind, andere Indizierungen für die Tabelle vorzunehmen und Spalten hinzuzufügen. Vermutlich wird diese Funktionalität gewünscht, also muss ich sie dem sqlite3 ddl-Zeug hinzufügen, wollte aber nur darauf hinweisen.

Ich wollte nur sicherstellen, dass Sie sich darüber im Klaren sind, dass Sie in sqlite3 nicht mehr in der Lage sind, andere Indizierungen für die Tabelle vorzunehmen und Spalten hinzuzufügen. Vermutlich wird diese Funktionalität gewünscht, also muss ich sie dem sqlite3 ddl-Zeug hinzufügen, wollte aber nur darauf hinweisen.

Sie meinen, Sie verlieren die Fähigkeit, normal Spalten hinzuzufügen, und müssen die gesamte Tabellenkopie ausführen?

Ja. Scheint die Geschichte zu sein, in der so ziemlich alles rund um das Ändern von SQLite funktioniert, außer jetzt geht es sogar darum, Spalten hinzuzufügen.

Wooohoooooo: Ballon: ... lol

In Ghost gibt es den Post-Markdown, den Titel und vielleicht die Tag-Namen, für die wir FTS ausführen möchten. Ich denke, zunächst einmal ... ich bin mir nicht sicher, ob das hilft.

Ich habe gerade entdeckt FULLTEXT ... MATCH in MySQL ( ein solches Noppe), eine Stunde lang versucht , eine zu zwingen fullText: function(name) { this.isFullText = name || true; return this; } in SchemaBuilder dann in Schuhanzieher versucht SchemaGrammar ohne scucess, dann ich diesen Thread gefunden;)

Benötigen Sie eine Finanzierung für 0.6 @tgriesser? Ich weiß nicht, wie du das schon gemacht hast :)

: +1:

@tgriesser @ErisDS Für sqllite und FTS würde es vielleicht funktionieren, diesem Muster zu folgen? http://peewee.readthedocs.org/en/latest/peewee/playhouse.html?highlight=full%20text#FTSModel Sie erstellen eine separate Tabelle, die speziell für den Volltextsuchindex verwendet wird. Auf diese Weise wird vermieden, dass alle Spalten in Text in der Haupttabelle geändert werden.

@dwstevens das könnte funktionieren, nicht sicher, wo wir hier auf FTS sind. Bookshelf unterstützt Plugins, vielleicht könnte so etwas mit einem Plugin und knex raw gemacht werden? Es wäre eine großartige Sache für jemanden, mit ihm zu spielen und zu sehen, ob er eine funktionierende Version zusammenstellen könnte.

Ich habe gerade ein Diskussionsproblem zu Ghost bezüglich der Implementierung der Suche angesprochen, das hier verlinkt ist . Es ist buchstäblich das älteste Problem in unserem Repository, und wir müssen es dringend vorantreiben.

@tgriesser Wie ist der Status hier in Knex? Gibt es Pläne? Wir könnten Ihren Input wirklich gebrauchen.

@ErisDS Unsere Lösung mit Sequelize bestand darin, rohe Sequelize-Abfragen für unsere FT-Indizes zu verwenden. Jetzt, da ich versuche, zu einem DAO-Muster zu wechseln und Knex zu verwenden, werde ich wahrscheinlich etwas Ähnliches implementieren. Es ist nicht so elegant wie eine integrierte Unterstützung, aber es reicht aus.

@tgriesser Ich würde gerne helfen, wenn ich kann!

@bomattin Ich denke, die meisten Leute verwenden

@ErisDS Ich werde anfangen, mich damit zu beschäftigen. Leider wird der größte Teil meiner Programmierzeit für die nächste Woche oder so darin bestehen, meine DAOs aufzubauen und zu versuchen, meine Kollegen daran zu verkaufen. Ich schaue mir die Knex-Codebasis an, wenn ich kann, damit ich versuchen kann, schnell einzutauchen und es richtig zu machen.

Hallo! Hast du Glück damit?

@ s-stude Leider keine Bewegung an meinem Ende. Das habe ich vorerst benutzt:

Users.find = function(params, options) {
    return new Promise(function(resolve, reject){
        var options = options? options : {};
        var whereclause;
        var lim = options.limit? options.limit : 65536; // Need a valid number here? 50 isn't a bad default.
        knex.select(cols.user)
            .from('users')
            .orWhereRaw('MATCH(firstname_preferred,lastname_preferred,username) AGAINST(? IN BOOLEAN MODE)', params.search)
            //.orWhereRaw('MATCH(groups.name) AGAINST(? IN BOOLEAN MODE)', '+matt*')
            .limit(lim)
            .then(function(userresults){
                resolve(new Users(userresults))
            })
            .catch(function(err){
                reject(err)
            });
    })
};

Irgendwelche Updates hier?

Folgendes verwende ich als Problemumgehung:

query.whereRaw('to_tsvector(parts.description) || to_tsvector(cars.engine_name)
        || to_tsvector(makes.name) || to_tsvector(models.name)
        || to_tsvector(part_types.name) || to_tsvector(part_types.description)
        || to_tsvector(part_categories.name)
        || to_tsvector(part_manufacturers.name) @@ to_tsquery(?)',req.query.search);

Ich habe mir http://knexjs.org/#Schema -index angesehen und das kleine Detail über "Der Indextyp wird nur von PostgreSQL unterstützt" übersehen. Daher habe ich im Rahmen meiner Migration Folgendes ausgeführt:

return knex.schema.table('host', t => {
  t.index('name', 'name_idx', 'FULLTEXT') # <<< I wish
})

resultierende .debug() Ausgabe gegen MySQL:

[ { sql: 'alter table `host` add index name_idx(`name`)',
    bindings: [] } ]

wo ich nehme an, es hätte add FULLTEXT index sagen sollen ... Gibt es etwas Besonderes, das die Verwendung des Type-Arguments für den MySQL-Dialekt blockiert?

Was ist damit passiert? Gibt es einen Überfall? Kann ich helfen?

@yamikuronue sicher, es sieht so aus, als würden große Datenbanken dies unterstützen, daher wäre eine gemeinsame API zum Erstellen eines Index

Wurde bereits gearbeitet, worauf ich aufbauen kann, oder sollte ich von vorne anfangen? Ich bin mir natürlich nicht sicher, ob ich dazu in der Lage sein werde, aber ich bin bereit, zumindest einen Blick darauf zu werfen

Kommentare zu Flut +1 und Statusaktualisierungsanforderung entfernt. Bitte verwenden Sie die Daumen für die Abstimmung

BEARBEITEN: Wenn dieser Feed keine neuen Nachrichten enthält, gibt es nichts Neues zu erzählen

Wie kann dies in der Zwischenzeit in einem Aufruf der obersten Ebene (dh createTable ) erfolgen, ohne dass raw für die gesamte CREATE TABLE -Anweisung verwendet werden muss? Oder müssen wir createTable , dann:

knex.raw('alter table `table` add fulltext (`col`)');

?

Das ist eigentlich gar nicht so nervig. Ich behalte alle meine Schemas in einem Verzeichnis, wobei die Dateinamen den Tabellennamen entsprechen. Für einige Tabellen foo , für die keine nicht unterstützten Anweisungen erforderlich sind:

// foo.js

module.exports = function (table) {
  table.string(...);
};

und für einige Tabellen bar , für die ein FULLTEXT Index erforderlich ist:

// bar.js

module.exports = {
  builder: function (table) {
    table.string(...);
  },
  raw: function () {
    return knex.raw('alter table `bar` add fulltext (`col`)');
  }
};

Dann habe ich einfach:

function createTable(table) {
  const schema = require('schemas/' + table);
  return (
    typeof schema === 'function'
      ? db.schema.createTable(table, schema)
      : db.schema.createTable(table, schema.builder)
        .then(() => schema.raw())
  ).catch(err => {
    logError(err.message);
  })
}

Dieses Problem war der Top-Hit für viele meiner Suchanfragen, hat aber meine Frage nicht beantwortet. Für diejenigen, die aus dem gleichen Grund auch hier landen ...

Postgres-Benutzer können einer tsvector-Spalte einen Volltextindex hinzufügen, indem sie das dritte Argument für table.index . Beispielsweise:

exports.up = (knex) => {
  return knex.schema.createTable('foo', (table) => {
    table.increments('id');
    table.specificType('fulltext', 'tsvector');

    table.index('fulltext', null, 'gin');
  );
);

Siehe auch:

https://knexjs.org/#Schema -index

und

https://stackoverflow.com/questions/45871474/how-to-add-gin-index-using-knex-js

@rapodaca Vielen Dank für Ihren Beitrag, diese Informationen zum Wiki hinzugefügt!

Dies kann auch eine hilfreiche Problemumgehung sein
http://blog.victorquinn.com/full-text-search-with-bookshelfjs

Funktioniert das noch für euch?
Ich habe versucht, table.index ('title', null, 'FULLTEXT') zu verwenden, und das SQL-Ergebnis lautet:
alter table `products` add index `products_title_index`(`title`)
Selbst wenn table.index ('title', null, 'BOOM') verwendet wird, gibt knex keinen Fehler aus und das SQL-Ergebnis ist dasselbe.

Habe ich etwas verpasst

Die Verwendung der RAW-Abfrage funktioniert.
ALTER TABLE products ADD FULLTEXT(title)

Leute) Ich habe mir eine Problemumgehung ohne .then () ausgedacht:
table.index(null, 'product_fulltext_index', "GIN (to_tsvector('english', name || ' ' || description)); SELECT NOW");

Also sollten Knex-Leute einfach () entfernen, wenn fieldName null ist und wir SELECT NOW Anhang loswerden könnten))

Gelöschter Kommentar, der völlig unabhängig war (über die allgemeine Verwendung von SQL-Indizes).

Es ist schon eine ganze Weile her, irgendwelche Updates?

Niemand hat noch nicht einmal richtig entworfen, wie das genau funktionieren soll. Die ordnungsgemäße Volltextsuche in Datenbanken war noch nie so einfach wie es sich anhört. Es wird nicht so fortschrittlich sein wie die richtigen FTS-Motoren, könnte aber für einige Anwendungsfälle nützlich sein ....

PRs wären auf jeden Fall sehr willkommen.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen