第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機(jī)立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何在 FaunaDB 中獲取包含子字符串的文檔

如何在 FaunaDB 中獲取包含子字符串的文檔

Go
動漫人物 2022-06-06 16:47:15
我正在嘗試檢索first名稱中包含字符串的所有任務(wù)文檔。我目前有以下代碼,但它只有在我傳遞確切名稱時才有效:res, err := db.client.Query(    f.Map(        f.Paginate(f.MatchTerm(f.Index("tasks_by_name"), "My first task")),        f.Lambda("ref", f.Get(f.Var("ref"))),    ),)我想我可以在ContainsStr()某處使用,但我不知道如何在我的查詢中使用它。另外,有沒有辦法在不使用的情況下做到這一點(diǎn)Filter()?我問是因?yàn)樗坪踉诜猪摵筮^濾,并且與頁面混淆
查看完整描述

1 回答

?
慕工程0101907

TA貢獻(xiàn)1887條經(jīng)驗(yàn) 獲得超5個贊

FaunaDB 提供了很多構(gòu)造,這使其功能強(qiáng)大,但您有很多選擇。強(qiáng)大的力量帶來了一個小的學(xué)習(xí)曲線:)。


如何閱讀代碼示例

為了清楚起見,我在這里使用了 FQL 的 JavaScript 風(fēng)格,并且通常從 JavaScript驅(qū)動程序公開 FQL 函數(shù),如下所示:


const faunadb = require('faunadb')

const q = faunadb.query

const {

  Not,

  Abort,

  ...

} = q

像這樣導(dǎo)出 Map 時必須小心,因?yàn)樗鼤c JavaScript 映射沖突。在這種情況下,您可以只使用 q.Map。


選項(xiàng) 1:使用 ContainsStr() 和過濾器

根據(jù)文檔的基本用法


ContainsStr('Fauna', 'a')

當(dāng)然,這適用于特定值,因此為了使其工作,您需要Filter 并且 Filter 僅適用于分頁集。這意味著我們首先需要獲得一個分頁集。獲取一組分頁文檔的一種方法是:


q.Map(

  Paginate(Documents(Collection('tasks'))),

  Lambda(['ref'], Get(Var('ref')))

)

但是我們可以更有效地做到這一點(diǎn),因?yàn)橐淮伍喿x === 一次閱讀并且我們不需要文檔,我們將過濾掉很多文檔。有趣的是,一個索引頁也是一次讀取,因此我們可以如下定義索引:


{

  name: "tasks_name_and_ref",

  unique: false,

  serialized: true,

  source: "tasks",

  terms: [],

  values: [

    {

      field: ["data", "name"]

    },

    {

      field: ["ref"]

    }

  ]

}

由于我們將 name 和 ref 添加到值中,索引將返回 name 和 ref 的頁面,然后我們可以使用它們進(jìn)行過濾。例如,我們可以對索引做類似的事情,對它們進(jìn)行映射,這將返回一個布爾數(shù)組。


Map(

  Paginate(Match(Index('tasks_name_and_ref'))),

  Lambda(['name', 'ref'], ContainsStr(Var('name'), 'first'))

)

由于 Filter 也適用于數(shù)組,我們實(shí)際上可以簡單地將Map替換為 filter。我們還將添加一個小寫字母以忽略大小寫,我們有我們需要的:


Filter(

  Paginate(Match(Index('tasks_name_and_ref'))),

  Lambda(['name', 'ref'], ContainsStr(LowerCase(Var('name')), 'first'))

)

就我而言,結(jié)果是:



{

  "data": [

    [

      "Firstly, we'll have to go and refactor this!",

      Ref(Collection("tasks"), "267120709035098631")

    ],

    [

      "go to a big rock-concert abroad, but let's not dive in headfirst",

      Ref(Collection("tasks"), "267120846106001926")

    ],

    [

      "The first thing to do is dance!",

      Ref(Collection("tasks"), "267120677201379847")

    ]

  ]

}

過濾和縮小頁面大小

正如您所提到的,這并不是您想要的,因?yàn)檫@也意味著如果您請求 500 個大小的頁面,它們可能會被過濾掉,您最終可能會得到一個大小為 3 的頁面,然后是 7 個頁面中的一個。您可能會認(rèn)為,為什么我不能只在頁面中獲取過濾后的元素?好吧,出于性能原因,這是一個好主意,因?yàn)樗旧蠙z查每個值。想象一下,你有一個龐大的集合并過濾掉了 99.99%。您可能必須遍歷許多元素才能達(dá)到 500,所有這些都需要讀取。我們希望定價是可預(yù)測的:)。


選項(xiàng) 2:索引!

每次你想做更高效的事情時,答案就在于索引。FaunaDB 為您提供了實(shí)現(xiàn)不同搜索策略的原始能力,但您必須有點(diǎn)創(chuàng)意,我在這里為您提供幫助:)。


綁定

在索引綁定中,您可以轉(zhuǎn)換文檔的屬性,在我們的第一次嘗試中,我們會將字符串拆分為單詞(我將實(shí)現(xiàn)多個,因?yàn)槲也煌耆_定您想要哪種匹配)


我們沒有字符串拆分功能,但由于 FQL 很容易擴(kuò)展,我們可以自己編寫它,綁定到我們宿主語言中的變量(在本例中為 javascript),或者使用這個社區(qū)驅(qū)動的庫中的一個:https://github .com/shiftx/faunadb-fql-lib


function StringSplit(string: ExprArg, delimiter = " "){

    return If(

        Not(IsString(string)),

        Abort("SplitString only accept strings"),

        q.Map(

            FindStrRegex(string, Concat(["[^\\", delimiter, "]+"])),

            Lambda("res", LowerCase(Select(["data"], Var("res"))))

        )

    )

)

并在我們的綁定中使用它。


CreateIndex({

  name: 'tasks_by_words',

  source: [

    {

      collection: Collection('tasks'),

      fields: {

        words: Query(Lambda('task', StringSplit(Select(['data', 'name']))))

      }

    }

  ],

  terms: [

    {

      binding: 'words'

    }

  ]

})

提示,如果你不確定你是否做對了,你總是可以用值而不是術(shù)語來綁定,然后你會在動物儀表板中看到你的索引是否真的包含值:

http://img1.sycdn.imooc.com//629dbf390001e3e014271146.jpg

我們做了什么?我們剛剛編寫了一個綁定,它將在寫入文檔時將值轉(zhuǎn)換為值數(shù)組。當(dāng)您在 FaunaDB 中索引文檔數(shù)組時,這些值是單獨(dú)的索引,但都指向同一個文檔,這對于我們的搜索實(shí)現(xiàn)非常有用。


我們現(xiàn)在可以使用以下查詢找到包含字符串“first”作為其單詞之一的任務(wù):


q.Map(

  Paginate(Match(Index('tasks_by_words'), 'first')),

  Lambda('ref', Get(Var('ref')))

)

這會給我一個文件名:“首先要做的是跳舞!”


其他兩個文檔沒有包含確切的單詞,那么我們該怎么做呢?


選項(xiàng) 3:索引和 Ngram(精確包含匹配)

為了獲得精確的包含匹配效率,您需要使用一個名為“NGram”的(仍然沒有記錄的函數(shù),因?yàn)槲覀儗頃蛊涓菀祝┖瘮?shù)。在 ngram 中劃分字符串是一種搜索技術(shù),通常在其他搜索引擎的底層使用。在 FaunaDB 中,由于索引和綁定的強(qiáng)大功能,我們可以輕松地應(yīng)用它。Fwitter 示例的源代碼中有一個自動完成的示例。此示例不適用于您的用例,但我確實(shí)為其他用戶引用了它,因?yàn)樗糜谧詣油瓿啥套址皇窍袢蝿?wù)一樣在較長字符串中搜索短字符串。


我們會根據(jù)您的用例對其進(jìn)行調(diào)整。在搜索方面,這完全是性能和存儲的權(quán)衡,在 FaunaDB 中,用戶可以選擇他們的權(quán)衡。請注意,在前面的方法中,我們分別存儲每個單詞,使用 Ngrams 我們將進(jìn)一步拆分單詞以提供某種形式的模糊匹配。不利的一面是,如果您做出錯誤的選擇,索引大小可能會變得非常大(搜索引擎同樣如此,因此它們讓您定義不同的算法)。


NGram 本質(zhì)上所做的是獲取一定長度的字符串的子字符串。例如:


NGram('lalala', 3, 3)

將返回:

http://img1.sycdn.imooc.com//629dbf460001f6b901810127.jpg

如果我們知道我們不會搜索超過某個長度的字符串,假設(shè)長度為 10(這是一個折衷,增加大小會增加存儲需求,但允許您查詢更長的字符串),您可以編寫跟隨 Ngram 生成器。


function GenerateNgrams(Phrase) {

  return Distinct(

    Union(

      Let(

        {

          // Reduce this array if you want less ngrams per word.

          indexes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],

          indexesFiltered: Filter(

            Var('indexes'),

            // filter out the ones below 0

            Lambda('l', GT(Var('l'), 0))

          ),

          ngramsArray: q.Map(Var('indexesFiltered'), Lambda('l', NGram(LowerCase(Var('Phrase')), Var('l'), Var('l'))))

        },

        Var('ngramsArray')

      )

    )

  )

}

然后,您可以按如下方式編寫索引:


CreateIndex({

  name: 'tasks_by_ngrams_exact',

  // we actually want to sort to get the shortest word that matches first

  source: [

    {

      // If your collections have the same property tht you want to access you can pass a list to the collection

      collection: [Collection('tasks')],

      fields: {

        wordparts: Query(Lambda('task', GenerateNgrams(Select(['data', 'name'], Var('task')))))

      }

    }

  ],

  terms: [

    {

      binding: 'wordparts'

    }

  ]

})

你有一個索引支持的搜索,你的頁面是你請求的大小。


q.Map(

  Paginate(Match(Index('tasks_by_ngrams_exact'), 'first')),

  Lambda('ref', Get(Var('ref')))

)

選項(xiàng) 4:索引和大小為 3 的 Ngram 或三元組(模糊匹配)

如果你想要模糊搜索,通常使用三元組,在這種情況下我們的索引會很容易,所以我們不會使用外部函數(shù)。


CreateIndex({

  name: 'tasks_by_ngrams',

  source: {

    collection: Collection('tasks'),

    fields: {

      ngrams: Query(Lambda('task', Distinct(NGram(LowerCase(Select(['data', 'name'], Var('task'))), 3, 3))))

    }

  },

  terms: [

    {

      binding: 'ngrams'

    }

  ]

})


如果我們再次將綁定放在值中以查看結(jié)果,我們將看到如下內(nèi)容:

http://img1.sycdn.imooc.com//629dbf6000017e2314801087.jpg

在這種方法中,我們在索引端和查詢端一樣使用兩個三元組。在查詢方面,這意味著我們搜索的“第一個”單詞也將被劃分為三元組,如下所示:

http://img1.sycdn.imooc.com//629dbf6a0001591d02720065.jpg

例如,我們現(xiàn)在可以進(jìn)行如下模糊搜索:


q.Map(

  Paginate(Union(q.Map(NGram('first', 3, 3), Lambda('ngram', Match(Index('tasks_by_ngrams'), Var('ngram')))))),

  Lambda('ref', Get(Var('ref')))

)

在這種情況下,我們實(shí)際上進(jìn)行了 3 次搜索,我們正在搜索所有三元組并將結(jié)果合并。這將返回我們所有包含 first 的句子。

http://img1.sycdn.imooc.com//629dbf760001c37b07760510.jpg

但是,如果我們拼錯了它并寫了frst,我們?nèi)匀粫ヅ渌腥齻€,因?yàn)橛幸粋€匹配的 trigram (rst)。



查看完整回答
反對 回復(fù) 2022-06-06
  • 1 回答
  • 0 關(guān)注
  • 130 瀏覽
慕課專欄
更多

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學(xué)習(xí)伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號