Firestore> = не возвращает результаты, как ожидалось - PullRequest
0 голосов
/ 28 марта 2020

Я снова использую >= запрос коллекции. Чтобы проверить скрипт, у меня просто есть 4 записи в моей коллекции.

Мой запрос:

 ...
.where("Workdesc", ">=", "imple") // no returning as expected
.get()
.then(querySnapshot => {
    querySnapshot.forEach(function(doc) {
        console.log("Result");
        console.log(doc.id, " ===> ", doc.data());
    });
  });

Workdesc из всех 4 документов -

  • "реализация kj"
  • "реализация hb срочно "
  • " требуется быстрый ответ по внедрению sharu "
  • " срочная работа по реализации cb "

Результат, по моему мнению, должен был вернуть все 4 документа, но это возвращается только 2. Я прилагаю скриншот журнала консоли и консоли Firebase:

enter image description here

enter image description here

Как вернуть результат с частичной буквой в любом месте строки.

Ответы [ 3 ]

0 голосов
/ 28 марта 2020

Чтобы основываться на ответе Дуга, к сожалению, Firestore не поддерживает тип поиска строки, который вы ищете. Потенциальное решение, которое устраняет текстовый поиск, состоит в том, что вы можете создать другое поле в ваших документах todo, в котором будет храниться информация о том, имеете ли вы дело с «реализацией».

Например, если у вас есть поле isImplementation, что будет истинно для задач реализации и ложно для тех, которые этого не делают, вы можете добавить это поле как часть предложения where в свой запрос. Это гарантирует, что вы выбираете только задачи реализации.

0 голосов
/ 28 марта 2020

Еще раз опираясь на @ Дуг ответ , Firestore - это проиндексированная база данных документов. Чтобы запросить данные, запрос должен быть выполнен к индексу за один раз, чтобы поддерживать производительность запросов в соответствии с тем, как устроена база данных.

Firebase не будет индексировать поля, которые являются строками по умолчанию, потому что это не ' Это эффективно, и это довольно обременительная операция в масштабе. Часто лучшим вариантом является другой подход.

Возьмем, к примеру, следующую функцию, которая разбивает входную строку на доступные для поиска части, которые затем могут быть добавлены в индекс. По мере увеличения длины входной строки количество подстрок, содержащихся внутри, быстро увеличивается.

function shatter(str, minLength = 1) {
    let parts = [str]; // always have full string
    let i, subLength = minLength;
    let strLength = str.length;
    while (subLength < strLength) {
        for (i = 0; i < (strLength - subLength + 1); i++) {
            parts.push(str.substring(i, i + subLength));
        }
        subLength++;
    }
    return parts;
}

Вот интерактивный фрагмент, демонстрирующий это:

function shatter(str, minLength = 1) {
    let parts = [str]; // always have full string
    let i, subLength = minLength;
    let strLength = str.length;
    while (subLength < strLength) {
        for (i = 0; i < (strLength - subLength + 1); i++) {
            parts.push(str.substring(i, i + subLength));
        }
        subLength++;
    }
    return parts;
}

let str = prompt('Please type out a string to shatter:', 'This is a test string');
let partsOfMin1 = shatter(str, 1);
console.log('Shattering into pieces of minimum length 1 gives:', partsOfMin1);
let partsOfMin3 = shatter(str, 3);
console.log('Shattering into pieces of minimum length 3 gives:', partsOfMin3);
let partsOfMin5 = shatter(str, 5);
console.log('Shattering into pieces of minimum length 5 gives:', partsOfMin5);
alert('The string "' + str + '" can be shattered into as many as ' + partsOfMin1.length + ' pieces.\r\n\r\nThis can be reduced to only ' + partsOfMin3.length + ' with a minimum length of 3 or ' + partsOfMin5.length + ' with a minimum length of 5.');

Однако, используя эту вышеупомянутую функцию, мы можем использовать ее так, чтобы она сохраняла разбитые фрагменты в Firestore на /substringIndex/todos/workDesc со ссылкой на документ, содержащий строку.

const firebase = require('firebase');
firebase.initializeApp(/* config here */);

const arrayUnion = firebase.firestore.FieldValue.arrayUnion;
const TODOS_COL_REF = firebase.firestore().collection('todos');
const SUBSTRING_INDEX_COL_REF = firebase.firestore().collection('substringIndex');

// splits given string into segments ranging from the given minimum length up to the full length
function shatter(str, minLength = 1) {
    let parts = [str];
    let i, subLength = minLength;
    let strLength = str.length;
    while (subLength < strLength) {
        for (i = 0; i < (strLength - subLength + 1); i++) {
            parts.push(str.substring(i, i + subLength));
        }
        subLength++;
    }
    return parts;
}

// upload data
const testData = {
    workDesc: 'this is a prolonged string to break code',
    assignDate: firebase.firestore.Timestamp.fromDate(new Date()),
    assignTo: 'Ddy1QVOAO6SIvB8LfAE8Z0Adj4H3',
    followers: ['Ddy1QVOAO6SIvB8LfAE8Z0Adj4H3'],
    searchArray: ['v1', 'v2']
}

const todoDocRef = TODOS_COL_REF.doc();
const todoId = todoDocRef.id;
todoDocRef.set(testData)
    .then(() => console.log('Uploaded test data!'))
    .catch((err) => console.error('Failed to test data!', err));

// Note: in this example, I'm not waiting for the above promise to finish
// Normally, you would integrate it into the batched write operations below

// index each desired string field
const indexDocRef = SUBSTRING_INDEX_COL_REF.doc('todos');
const indexedFields = ["workDesc"];
const indexEntryMinLength = 3;

const indexUpdatePromises = indexedFields.map((fieldName) => {
    const indexColRef = indexDocRef.collection(fieldName);
    const fieldValue = testData[fieldName];
    if (typeof fieldValue !== 'string') return Promise.resolve(undefined); // skip non-string values

    const parts = shatter(fieldValue, indexEntryMinLength);

    console.log('INFO: Consuming ' + (parts.length * 2) + ' write operations to index ' + fieldName);

    // Each batched write can handle up to 500 operations, each arrayUnion counts as two
    const partsBatches = [];
    if (parts.length > 250) {
        for (let i = 0; i < parts.length; i += 250) {
            partsBatches.push(parts.slice(i, i + 250));
        }
    } else {
        partsBatches.push(parts);
    }

    const batchCommitPromises = partsBatches
        .map((partsInBatch) => {
            const batch = firebase.firestore().batch();
            partsInBatch.forEach((part) => {
                batch.set(indexColRef.doc(part), {ids: arrayUnion(todoId)}, { merge: true })
            })
            return batch.commit();
        });

    return Promise.all(batchCommitPromises);
})

Promise.all(indexUpdatePromises)
    .then(() => console.log('Uploaded substring index!'))
    .catch((err) => console.error('Failed to upload index!', err));

Затем, когда вы хотите найти все документы, содержащие "impl", вы будете использовать следующее для получения массива совпадающих идентификаторов документов:

firebase.firestore().doc('substringIndex/todos/workDesc/impl').get()
  .then(snap => snap.get('ids'))
  .then(console.log, console.error)

Пока работает приведенный выше код, когда вы обновите индекс, вы достаточно быстро достигнете своих пределов чтения / записи, и вы, скорее всего, столкнетесь с проблемами параллелизма. Я также считаю это fr agile в том, что не-Engli sh символы и знаки препинания также сбивают его с толку - это включено только в качестве демонстрации. Именно из-за этих проблем в соответствующей документации Firebase рекомендуется использовать стороннюю службу поиска, такую ​​как Algolia , для полнотекстового поиска.

TL: DR;

Лучшее решение - иметь удобочитаемую форму ваших данных ("sharu implementation quick response needed") и индексируемую форму ваших данных ({implementation: true, urgent: true, pending: true}) в соответствии с @ Luis в их ответ .

0 голосов
/ 28 марта 2020

Ваш запрос работает как положено. Когда вы выполняете сравнение со строками, они сортируются лексикографически или, другими словами, по алфавиту. Вот фактический порядок сортировки каждого значения, и где «impl» сортирует среди них:

  1. «срочная задача выполнения cb»
  2. «срочная реализация hb»
  3. "impl"
  4. "реализация kj"
  5. "нужен быстрый ответ для реализации sharu"

В алфавитном порядке вы можете видеть, что "k" и "s" идут после "я". Таким образом, это единственные документы, которые вы получите из запроса, где значения Workdes c на превышают"impl".

Если вы пытаетесь создать подстроку выполнить поиск, чтобы найти все строки Workdes c, которые содержат"impl", что невозможно с Firestore. Firestore не предлагает поиск по подстроке. Вам нужно будет найти другой способ (возможно, зеркальное отображение данных в другой базе данных, которая его поддерживает).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...