首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >德语MongoDB文本索引

德语MongoDB文本索引
EN

Stack Overflow用户
提问于 2015-02-21 14:00:32
回答 3查看 963关注 0票数 8

在我的文章集合中,我有一个文本索引:

代码语言:javascript
复制
{
    "v" : 1,
    "key" : {
            "_fts" : "text",
            "_ftsx" : 1
    },
    "name" : "title_text_abstract_text_body_text",
    "ns" : "foo.articles",
    "weights" : {
            "abstract" : 1,
            "body" : 1,
            "title" : 1
    },
    "default_language" : "english",
    "language_override" : "language",
    "textIndexVersion" : 2
}

在我的文章集合中,我有这样一个条目:

代码语言:javascript
复制
{
    "_id" : ObjectId("5477c28c807a9cd660ccd567"),
    "title" : "Hallo Welt!",
    "author" : "foo",
    "publishDate" : ISODate("2014-11-28T17:00:00Z"),
    "language" : "de",
    "abstract" : "Mein erster Artikel!",
    "body" : "Dieser Artikel ist in deutscher Sprache.",
    "__v" : 0
}

(实际上abstractbody中有不同的值,为了简洁起见,让我们假设它是上面的那些)

当我尝试搜索本文时:

代码语言:javascript
复制
db.articles.find({$text: {$search: 'Welt'}})

它确实被找到了。

但是:当我试图搜索本文时:

代码语言:javascript
复制
db.articles.find({$text: {$search: 'Sprache'}})

我没有得到任何结果。但是,在我将language更改为ennone之后,我确实得到了本文的结果,并使用了完全相同的查询。

我做错了什么?

编辑:根据注释中的请求,这里提供了导致上述行为的确切命令。一开始就应该这样做的,抱歉。

代码语言:javascript
复制
> db.test.drop()
true
> db.test.insert({language: "de", body: "vermutlich", title: "Artikel"})
WriteResult({ "nInserted" : 1 })
> db.test.ensureIndex({body: "text", title: "text"})
{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 2,
        "ok" : 1
}
> db.test.find({$text: {$search: 'vermutlich'}})
> db.test.find({$text: {$search: 'Artikel'}})
{ "_id" : ObjectId("54ea86d6c9ec98269e022c67"), "language" : "de", "body" : "vermutlich", "title" : "Artikel" }
> db.version()
2.6.5

我还试着再一次改变语言:

代码语言:javascript
复制
> db.test.update({}, {$set: {language: "en"}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.test.find({$text: {$search: 'Artikel'}})
{ "_id" : ObjectId("54ea86d6c9ec98269e022c67"), "language" : "en", "body" : "vermutlich", "title" : "Artikel" }
> db.test.find({$text: {$search: 'vermutlich'}})
{ "_id" : ObjectId("54ea86d6c9ec98269e022c67"), "language" : "en", "body" : "vermutlich", "title" : "Artikel" }

编辑:,好的,我只是尝试重建这个例子。,但我也添加了一个德语引语,这就是我所做的:

代码语言:javascript
复制
> db.test.drop()
true
> db.test.insert({ language: "portuguese", original: "A sorte protege os audazes.", translation: [{ language: "english", quote: "Fortune favors the bold."},{ language: "spanish", quote: "La suerte rotege a los audaces."}]})
WriteResult({ "nInserted" : 1 })
> db.test.insert({ language: "spanish", original: "Nada hay más surrealista que la realidad.", translation:[{language: "english",quote: "There is nothing more surreal than reality."},{language: "french",quote: "Il n'y a rien de plus surréaliste que la réalité."}]})
WriteResult({ "nInserted" : 1 })
> db.test.insert({ original: "is thisdagger which I see before me.", translation: {language: "spanish",quote: "Es este un puñal que veo delante de mí." }})
WriteResult({ "nInserted" : 1 })
> db.test.insert({original: "Die Geister, die ich rief...", language: "german", translation: {language: "english", quote: "The spirits that I've cited..."}})
WriteResult({ "nInserted" : 1 })
> db.test.ensureIndex( { original: "text", "translation.quote": "text" } )
{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 2,
        "ok" : 1
}

然后我问了几个问题:

代码语言:javascript
复制
> db.test.count({$text: {$search: "delante"}})
1
> db.test.count({$text: {$search: "spirits"}})
1
> db.test.count({$text: {$search: "Geister"}})
0

结论: mongoDB不适用于德语?这真是令人沮丧

EN

回答 3

Stack Overflow用户

发布于 2015-03-01 20:38:51

wdberkeley是正确的,但是我感觉到添加堵住的快速解释的冲动,因为我怀疑没有这个领域经验的用户会得到这个要点。我还想强调一些替代方案和一般限制。

在许多语言中,单词因语法规则而发生显著变化,例如德语单词"Geist“(心/鬼/灵):

代码语言:javascript
复制
"Geist" (singular) -> "Geister" (plural) -> "Geistern" (plural accusative)

这种影响在英语中也是众所周知的,但不那么明显,例如:

代码语言:javascript
复制
"house" -> "houses" // "mouse" -> "mice" // "notable" -> "notably"

通常,我们希望搜索忽略本地语法结构,所以如果我们在寻找"Geist",它应该找到上面的任何一个单词。这样做是极具挑战性的,因为语言规则是复杂的,没有上下文就不能确定正确的答案。

后缀剥离是一种常见的、相对简单的方法,它假设某些结尾非常可能只是结尾,并且可以被移除以获得词干。有时,词干分析器故意删除实际上属于词干的字母,例如"notable" -> "notabl"

由于引号的语言是已知的,正确的词干将用于引号。这是可行的-与你的数据:

代码语言:javascript
复制
> db.test.find({$text: {$search: 'Geist'}}).count()
1

现在的问题是,用户可能不是在寻找茎,而是寻找派生表单,因此我们需要对输入应用相同的转换。关键的问题是,我们一开始不知道应用了哪种转换。所以你试图做一些已经很复杂的事情,加上一个变量。

好的是有雪球,它是MongoDB和其他搜索系统(如SolR )使用的词干器。它可以在BSD许可下使用,并被移植到多种语言中,因此可以在客户端代码中使用数据库完成相同的操作。这样,我们就不会把DB当作黑匣子,但我们也会将客户端代码与数据库的实现细节相结合.选择你的毒药。

例如,我们可以运行所有的词干器,看看哪一个改变了输入,但这可能会导致fals阳性,因为这个词可能已经是一个词干,而来自另一种语言的词干器会缩短它(德语词干分析器:'mice' -> 'mic')。

至少,如果我们采用词干器的一组不同的响应,那么我们需要的查询数量就会大大减少。

或者,您可以参考单词列表来猜测该查询使用的是哪种语言。

即使有了这些额外的努力,也必须理解通过简单的后缀剥离所做的限制。例如,在寻找“老鼠”时,“老鼠”是找不到的,即使用英语词干器也找不到,因为词干器假定茎更短。如果这些文本不是真的用他们认为的语言,事情就会变得更糟(尤利西斯.)

换句话说,一个真正好的自由文本搜索需要的不仅仅是词干,跨语言的查询也增加了这一点。一个不同的搜索数据库不是灵丹妙药 -这个问题深深地植根于问题空间.

编辑:ElasticSearch对堵塞有一个很好的全面解释。 (我在写完答案后一直找到这些)

EDIT2:

为什么MongoDB不能简单地使用不同的词干词?

转换仅在插入或更新数据库中的文本时应用。查询只需查找与词干匹配的内容。从本质上说,索引是由词根词构成的。你想要的每一次都需要走遍整个收藏品。这将是非常低效率的,并且违背了索引的目的。您可以做的是按照建议在客户端代码中执行该步骤。

为什么我不能用$or搜索两次文本索引

AFAIK,这是查询引擎的一个限制--可能与排名有关,因为根据两个不同的输入进行一个好的评分没有多大意义。但是您可以简单地运行两个查询并合并结果客户端。

票数 4
EN

Stack Overflow用户

发布于 2015-02-24 21:23:57

抱歉,我当时很傻。问题很简单:我们正在尝试将搜索文本"vermutlich"与文档文本"vermutlich"匹配,要正确地实现这一点,您需要使用相同的语言规则来解析这两种语言。如果您做了以下操作:

代码语言:javascript
复制
> db.test.drop()
> db.test.insert({ "language" : "de", "body" : "vermutlich", "title" : "Artikel"})
> db.test.ensureIndex({ "$**" : "text" })
> db.test.count({ "$text" : { "$search" : "vermutlich" } })
0
> db.test.count({ "$text" : { "$search" : "vermutlich", "$language" : "de" } })
1

第一个查询搜索文档,该文档由于language字段而被索引为德语,使用作为英语单词处理的"vermutlich"

可以为文本索引设置默认语言,以避免在每个查询中指定$language

代码语言:javascript
复制
> db.test.drop()
> db.test.insert({ "language" : "de", "body" : "vermutlich", "title" : "Artikel"})
> db.test.ensureIndex({ "$**" : "text" }, { "default_language" : "de" })
> db.test.count({ "$text" : { "$search" : "vermutlich" } })
1
票数 1
EN

Stack Overflow用户

发布于 2015-02-26 13:31:34

作为解决办法,我用default_language: "none"language_override: "none"创建了文本索引。这样就没有停止的话语,也没有词根。但至少我不管语言如何都能找到直接的匹配。

代码语言:javascript
复制
> db.test.drop()
true
> db.test.insert({ language: "portuguese", original: "A sorte protege os audazes.", translation: [{ language: "english", quote: "Fortune favors the bold."},{ language: "spanish", quote: "La suerte rotege a los audaces."}]})
WriteResult({ "nInserted" : 1 })
> db.test.insert({ language: "spanish", original: "Nada hay más surrealista que la realidad.", translation:[{language: "english",quote: "There is nothing more surreal than reality."},{language: "french",quote: "Il n'y a rien de plus surréaliste que la réalité."}]})
WriteResult({ "nInserted" : 1 })
> db.test.insert({ original: "is this dagger which I see before me.", translation: {language: "spanish",quote: "Es este un puñal que veo delante de mí." }})
WriteResult({ "nInserted" : 1 })
> db.test.insert({original: "Die Geister, die ich rief...", language: "german", translation: {language: "english", quote: "The spirits that I've cited..."}})
WriteResult({ "nInserted" : 1 })
> db.test.ensureIndex( { original: "text", "translation.quote": "text" }, {default_language: 'none', language_override: 'none'} )
{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 2,
        "ok" : 1
}
> db.test.find({$text: {$search: 'Geister'}})
{ "_id" : ObjectId("54ed31b2e7ac93c32c760809"), "original" : "Die Geister, die ich rief...", "language" : "german", "translation" : { "language" : "english", "quote" : "The spirits that I've cited..." } }

除非有人找到一个实际的解决方案,否则我认为mongoDB文本索引被破坏了。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28646646

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档