4

MongoDB の上に単純化されたバージョンの検索エンジンを構築しています。

サンプルデータセット

{ "_id" : 1, "dept" : "tech", "updDate":  ISODate("2014-08-27T09:45:35Z"), "description" : "lime green computer" }
{ "_id" : 2, "dept" : "tech", "updDate":  ISODate("2014-07-27T09:45:35Z"), "description" : "wireless red mouse" }
{ "_id" : 3, "dept" : "kitchen", "updDate":  ISODate("2014-04-27T09:45:35Z"), "description" : "green placemat" }
{ "_id" : 4, "dept" : "kitchen", "updDate":  ISODate("2014-05-27T09:45:35Z"), "description" : "red peeler" }
{ "_id" : 5, "dept" : "food", "updDate":  ISODate("2014-04-27T09:45:35Z"), "description" : "green apple" }
{ "_id" : 6, "dept" : "food", "updDate":  ISODate("2014-01-27T09:45:35Z"), "description" : "red potato" }
{ "_id" : 7, "dept" : "food", "updDate":  ISODate("2014-08-28T09:45:35Z"), "description" : "lime green computer" }
{ "_id" : 8, "dept" : "food", "updDate":  ISODate("2014-08-27T09:45:35Z"), "description" : "lime green computer" }
{ "_id" : 9, "dept" : "food", "updDate":  ISODate("2014-08-27T09:45:35Z"), "description" : "lime green computer" }

「offset-limit」を使用して結果をページ分割することは避けたいと考えています。これを行うには、基本的に「seek メソッド」を使用して、クエリの「where/match」句を変更してインデックスを使用できるようにします。コレクションを繰り返し処理して目的の結果を取得する代わりに。「シーク メソッド」の詳細については、 http: //use-the-index-luke.com/blog/2013-07/pagination-done-the-postgresql-wayを読むことを強くお勧めします。

通常、検索エンジンは結果をスコアで並べ替え、日付を更新して降順で並べます。これを実現するために、次のように集計パイプラインでテキスト検索機能を使用しています。

db.inventory.createIndex({description:"text", dept: -1, updDate: -1, id:-1})

先頭ページ

db.inventory.aggregate(  [ { $match: { dept : {$in : ["food","kitchen"]},"$text" : { "$language" : "en", "$search" : "green"} } },{ $project: {score: { $meta: "textScore" }, description : 1, updDate : 1, _id: 1 } }, { $sort: { "score" : -1, "updDate" : -1, _id: -1 } }, {$limit:  2 }]  )


{ "_id" : 5, "updDate" : ISODate("2014-04-27T09:45:35Z"), "description" : "green apple", "score" : 0.75 }
{ "_id" : 3, "updDate" : ISODate("2014-04-27T09:45:35Z"), "description" : "green placemat", "score" : 0.75 }

2 ページ目

db.inventory.aggregate(  [ { $match: { dept : {$in : ["food","kitchen"]},"$text" : { "$language" : "en", "$search" : "green"} } },{ $project: {score: { $meta: "textScore" }, description : 1, updDate : 1, _id: 1 } }, { $sort: { "score" : -1, "updDate" : -1, _id: -1 } }, { "$match" : { "$or" : [ { "score" : { "$lt" : 0.75}} , { "$and" : [ { "score" : { "$eq" : 0.75}} , { "$or" : [ { "updDate" : { "$lt" : ISODate("2014-04-27T09:45:35Z")}},{ "$and" : [ { "updDate": { "$eq" : ISODate("2014-04-27T09:45:35Z")}} , { "_id" : { "$lt" : 3}}]}]}]}]}},{$limit:  2 }]  )

{ "_id" : 7, "updDate" : ISODate("2014-08-28T09:45:35Z"), "description" : "lime green computer", "score" : 0.6666666666666666 }
{ "_id" : 9, "updDate" : ISODate("2014-08-27T09:45:35Z"), "description" : "lime green computer", "score" : 0.6666666666666666 }

そして最後のページ

db.inventory.aggregate(  [ { $match: { dept : {$in : ["food","kitchen"]} , "$text" : { "$language" : "en", "$search" : "green"} } }, { $project: {score: { $meta: "textScore" }, description : 1, updDate : 1, _id: 1 } }, { $sort: { "score" : -1, "updDate" : -1, _id: -1 } }, { "$match" : { "$or" : [ { "score" : { "$lt" : 0.6666666666666666}} , { "$and" : [ { "score" : { "$eq" : 0.6666666666666666}} , { "$or" : [ { "updDate" : { "$lt" : ISODate("2014-08-27T09:45:35Z")}} , { "$and" : [ { "updDate" : { "$eq" : ISODate("2014-08-27T09:45:35Z")}} , { "_id" : { "$lt" : 9}}]}]}]}]}}, {$limit:  2 }]  )


{ "_id" : 8, "updDate" : ISODate("2014-08-27T09:45:35Z"), "description" : "lime green computer", "score" : 0.6666666666666666 }

結果をスコア、updDate、および ID で並べ替える方法と、2 番目の一致フェーズで、ドキュメントのスコア値、更新日、および最後に ID を使用してそれらをページ分割しようとする方法に注目してください。

インデックスの作成では、テキスト インデックス プレフィックス フィールドでテキスト クエリをカバーできないことが考慮されています。問題https://jira.mongodb.org/browse/SERVER-13018を参照してください。

「executionStats」モードと「allPlansExecution」モードは集約フレームワークでは機能しないため、https: //jira.mongodb.org/browse/SERVER-19758 を参照してください。MongoDBがどのようにクエリを解決しようとしているのかわかりません。

インデックスの交差はテキスト検索では機能しないため、https: //jira.mongodb.org/browse/SERVER-3071 (2.5.5 で解決済み) およびhttp://blog.mongodb.org/post/87790974798/effectiveを参照してください。 -indexing-in-mongodb-26著者が言う場所

As of version 2.6.0, you cannot intersect with geo or text indices and you can intersect at most 2 separate indices with each other. These limitations are likely to change in a future release.

https://docs.mongodb.org/manual/MongoDB-indexes-guide-master.pdfのセクション 3.4(Text Search Tutorials) および 3.5(Indexing Strategies) を何度か読んだ後、明確な結論に達しませんでした。

では、テキスト検索の観点から、このコレクションをインデックス化するための最良のインデックス戦略は何でしょうか?

最初の一致フェーズの 1 つのインデックスと 2 番目の (ページネーション) 一致フェーズの別のインデックス?

db.inventory.createIndex({description:"text", dept: -1})
db.inventory.createIndex({updDate: -1, id:-})

両方の一致フェーズのフィールドを考慮した複合インデックス?

db.inventory.createIndex({description:"text", dept: -1, updDate: -1, id:-1})

上記のどれでもない?

ありがとう

4

0 に答える 0