139 lines
3.8 KiB
Go
139 lines
3.8 KiB
Go
![]() |
// Copyright (c) 2014 Couchbase, Inc.
|
||
|
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
|
||
|
// except in compliance with the License. You may obtain a copy of the License at
|
||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||
|
// Unless required by applicable law or agreed to in writing, software distributed under the
|
||
|
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||
|
// either express or implied. See the License for the specific language governing permissions
|
||
|
// and limitations under the License.
|
||
|
|
||
|
package upside_down
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
|
||
|
"github.com/blevesearch/bleve/document"
|
||
|
"github.com/blevesearch/bleve/index"
|
||
|
"github.com/blevesearch/bleve/index/store"
|
||
|
)
|
||
|
|
||
|
type IndexReader struct {
|
||
|
index *UpsideDownCouch
|
||
|
kvreader store.KVReader
|
||
|
docCount uint64
|
||
|
}
|
||
|
|
||
|
func (i *IndexReader) TermFieldReader(term []byte, fieldName string) (index.TermFieldReader, error) {
|
||
|
fieldIndex, fieldExists := i.index.fieldIndexes[fieldName]
|
||
|
if fieldExists {
|
||
|
return newUpsideDownCouchTermFieldReader(i, term, uint16(fieldIndex))
|
||
|
}
|
||
|
return newUpsideDownCouchTermFieldReader(i, []byte{ByteSeparator}, ^uint16(0))
|
||
|
}
|
||
|
|
||
|
func (i *IndexReader) FieldReader(fieldName string, startTerm []byte, endTerm []byte) (index.FieldReader, error) {
|
||
|
fieldIndex, fieldExists := i.index.fieldIndexes[fieldName]
|
||
|
if fieldExists {
|
||
|
return newUpsideDownCouchFieldReader(i, uint16(fieldIndex), startTerm, endTerm)
|
||
|
}
|
||
|
return newUpsideDownCouchTermFieldReader(i, []byte{ByteSeparator}, ^uint16(0))
|
||
|
}
|
||
|
|
||
|
func (i *IndexReader) DocIDReader(start, end string) (index.DocIDReader, error) {
|
||
|
return newUpsideDownCouchDocIDReader(i, start, end)
|
||
|
}
|
||
|
|
||
|
func (i *IndexReader) Document(id string) (*document.Document, error) {
|
||
|
// first hit the back index to confirm doc exists
|
||
|
backIndexRow, err := i.index.backIndexRowForDoc(i.kvreader, id)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
if backIndexRow == nil {
|
||
|
return nil, nil
|
||
|
}
|
||
|
rv := document.NewDocument(id)
|
||
|
storedRow := NewStoredRow(id, 0, []uint64{}, 'x', nil)
|
||
|
storedRowScanPrefix := storedRow.ScanPrefixForDoc()
|
||
|
it := i.kvreader.Iterator(storedRowScanPrefix)
|
||
|
defer it.Close()
|
||
|
key, val, valid := it.Current()
|
||
|
for valid {
|
||
|
if !bytes.HasPrefix(key, storedRowScanPrefix) {
|
||
|
break
|
||
|
}
|
||
|
row, err := NewStoredRowKV(key, val)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
if row != nil {
|
||
|
fieldName := i.index.fieldIndexToName(row.field)
|
||
|
field := decodeFieldType(row.typ, fieldName, row.value)
|
||
|
if field != nil {
|
||
|
rv.AddField(field)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
it.Next()
|
||
|
key, val, valid = it.Current()
|
||
|
}
|
||
|
return rv, nil
|
||
|
}
|
||
|
|
||
|
func (i *IndexReader) DocumentFieldTerms(id string) (index.FieldTerms, error) {
|
||
|
back, err := i.index.backIndexRowForDoc(i.kvreader, id)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
rv := make(index.FieldTerms, len(back.termEntries))
|
||
|
for _, entry := range back.termEntries {
|
||
|
fieldName := i.index.fieldIndexToName(uint16(*entry.Field))
|
||
|
terms, ok := rv[fieldName]
|
||
|
if !ok {
|
||
|
terms = make([]string, 0)
|
||
|
}
|
||
|
terms = append(terms, *entry.Term)
|
||
|
rv[fieldName] = terms
|
||
|
}
|
||
|
return rv, nil
|
||
|
}
|
||
|
|
||
|
func (i *IndexReader) Fields() ([]string, error) {
|
||
|
rv := make([]string, 0)
|
||
|
it := i.kvreader.Iterator([]byte{'f'})
|
||
|
defer it.Close()
|
||
|
key, val, valid := it.Current()
|
||
|
for valid {
|
||
|
if !bytes.HasPrefix(key, []byte{'f'}) {
|
||
|
break
|
||
|
}
|
||
|
row, err := ParseFromKeyValue(key, val)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
if row != nil {
|
||
|
fieldRow, ok := row.(*FieldRow)
|
||
|
if ok {
|
||
|
rv = append(rv, fieldRow.name)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
it.Next()
|
||
|
key, val, valid = it.Current()
|
||
|
}
|
||
|
return rv, nil
|
||
|
}
|
||
|
|
||
|
func (i *IndexReader) GetInternal(key []byte) ([]byte, error) {
|
||
|
internalRow := NewInternalRow(key, nil)
|
||
|
return i.kvreader.Get(internalRow.Key())
|
||
|
}
|
||
|
|
||
|
func (i *IndexReader) DocCount() uint64 {
|
||
|
return i.docCount
|
||
|
}
|
||
|
|
||
|
func (i *IndexReader) Close() {
|
||
|
i.kvreader.Close()
|
||
|
}
|