0

I'm using YDN-DB (an abstraction on top of IndexedDB) as a local database. I have an object store called 'conversations', and in that store, there's an index called 'participants' where there is a string containing id's for different users in the conversation. For example:

Example Conversation #1:

id: 1234343434353456,
participants: '171e66ca-207f-4ba9-8197-d1dac32499db,82be80e2-2831-4f7d-a8d7-9223a2d4d511'

Example Conversation #2:

id: 4321343434356543,
participants: 'd7fa26b3-4ecc-4f84-9271-e15843fcc83f,171e66ca-207f-4ba9-8197-d1dac32499db'

To try to perform a partial match on an index, I tried using ydn-db-fulltext as a solution. The full text catalog looks like this:

  {
    name: 'participants',
    lang: 'en',
    sources: [
      {
        storeName: 'conversations',
        keyPath: 'participants',
        weight: 1
      }
    ]
  }

I see that the catalog is generated, but there seems to be a problem doing exact matches. For example, if I query using only part of the key in the participants index, I get back a primary key from the catalog:

db.search('participants', 'd7fa26b3').done(function(results) {
  if(results.length == 0) console.debug('No results found...');
  console.debug(results);                  // there is 1 object here!
  var primaryKey = results[0].primaryKey;  // primaryKey exists!
});

However, when using any value past the '-', the search request returns 0 results:

db.search('participants', 'd7fa26b3-4ecc-4f84-9271-e15843fcc83f').done(function(results) {
  if(results.length == 0) console.debug('No results found...');
  console.debug(results);                  // there are 0 objects in the array
  var primaryKey = results[0].primaryKey;  // primaryKey throws undefined since there are 0 results!
});

This makes sense, when reading the documentation, in that '-' and '*' are reserved characters that remove a phrase and match a prefix respectively:

Query format is free text, in which implicit and/or/near logic operator apply for each token. Use double quote for exact match, - to subtract from the result and * for prefix search.

I tried putting double quotes inside the single quotes, using only double quotes, and also escaping all of the '-' characters with a backslash, but none of these seem to work.

So the question is how does one perform a match in an index where the string contains '-' characters?

jamesmortensen
  • 33,636
  • 11
  • 99
  • 120

2 Answers2

1

Have you try db.search('participants', '"d7fa26b3"').

BTW, you are using full text search that is not suppose to do. You have to tokenize your string and index them manually.

Kyaw Tun
  • 12,447
  • 10
  • 56
  • 83
  • No, but I tried `db.search('"d7fa26b3-4ecc-4f84-9271-e15843fcc83f'")` unsuccessfully. If I tokenize these manually instead of using fulltext, does that mean I need an extra table to map primary keys to these participant pins? – jamesmortensen Jul 17 '14 at 23:56
  • BTW the partial pin in double quotes worked, but I was hoping to use the full pin for a more exact match. Hope this helps clarify. – jamesmortensen Jul 17 '14 at 23:57
  • Also, I should be clear that the fulltext catalog 'participants' is the same name as the index in the 'conversations' object store. So I have a table already called 'participants' which has the k and v indeces used by the fulltext module. Hope this helps. – jamesmortensen Jul 18 '14 at 00:06
  • sorry @jmort253 full text search won't work in your case. There is another technique called http://en.wikipedia.org/wiki/Trie or just index the string you want to search. – Kyaw Tun Jul 18 '14 at 00:09
  • By "index the string" do you mean I need to create a new object store that maps participant pins to conversation primary keys? I already have the participants property marked as an index key in the schema, but I don't see anything in the API that allows me to select based on a partial string? Thanks again! – jamesmortensen Jul 18 '14 at 00:14
  • 2
    If you store the participants field of your object as an array, then you can use the multi-entry flag to the createIndex method called on the participants field, and probably do what you want. – Josh Jul 18 '14 at 01:11
  • @Josh - Only problem with that is that the number of participants varies. Please correct me if I'm wrong, but I believe multi-entry expects there to be (a) a fixed number of items in the array, and (b) that every array element be used when retrieving values from the index. Instead, I'll be retrieving conversations using only one of the participant pins. Hope this helps clarify. – jamesmortensen Jul 18 '14 at 15:49
  • a is wrong. b is both right and wrong. b is right that every element is used, but b is wrong because you can make the decision of what to include when querying over the set generated by b, by using IDBKeyRange parameter to openCursor. – Josh Jul 18 '14 at 16:32
  • @Josh - Okay, it looks like I'm going to take a different approach because I really only need to query for conversations where there are only two people in them. However, that's useful information that may definitely help others. If you put all that in an answer, I'll up vote it. Thank you! – jamesmortensen Jul 18 '14 at 18:27
1

If you store the participants field of your object as an array, then you can use the multi-entry flag to the createIndex method called on the participants field, and probably do what you want.

The number of items in the participants property of the object is mutable. When you update an object in the store and it has a different number of items in the partic property, then the index is automatically updated as a result (just like any other index). If you add an item to the prop, then restore (put/override/cursor.update) the object in the store, the index updates.

It helps to review the basics of how a multi-entry index works. You can do this with vanilla js, without a framework, and certainly without full-text searching.

Josh
  • 17,834
  • 7
  • 50
  • 68