【问题标题】:How to check all the collections in a MongoDB database for a particular keyword?如何检查 MongoDB 数据库中的所有集合以查找特定关键字?
【发布时间】:2020-02-26 14:51:03
【问题描述】:

我目前正在开发一个使用 Mongoose 查询的 NodeJS 项目。

出现了一个新要求,我无法理解如何解决。我想获取一个查询字符串并在我的数据库的所有集合中搜索它以返回与该值匹配的对象。

这就是我的收藏的样子:

书籍:

{
    "book_id": "ab12nld”,
    "book_version": "0”,
    "author": “Sam”,
    “name”: “Sample Book”,
    “comments”: “Done”
  },
  {
    "book_id": "a5g2nld”,
    "book_version": "1",
    "author": "Martin",
    "name": "Sample Book",
    “comments”: “In Progress”
  }

汽车:

{
    "car_id": "nlp240n”,
    "car_model": "3”,
    "brand": “Hyundai”,
    “name”: “Verna”,
    “color”: “Blue”
  },
  {
    "car_id": "cak201n”,
    "car_model": "1”,
    "brand": “Tata”,
    “name”: “Indica”,
    “color”: “Black”
  }

电话:

{
    "phone_id": "n0830bo”,
    "brand": “OnePlus”,
    “name”: “7 Pro”,
    “color”: “Red”
  },
  {
    "phone_id": "bh97b01”,
    "brand": “IPhone”,
    “name”: “11 Pro”,
    “color”: “Black”
  }

我会得到一个query_string,它将在这个集合中搜索,如果有匹配的结果,我应该得到所有相关的值。

例子:

如果query_stringMartin,我应该从Books 集合中得到相应的结果,因为Martin 只存在于那里:

 {
    "book_id": "a5g2nld”,
    "book_version": "1",
    "author": "Martin",
    "name": "Sample Book",
    “comments”: “In Progress”
  }

如果query_stringBlack,我应该从 Cars 和 Phones 集合中得到相应的结果,因为它们的值都是 Black

{
    "car_id": "cak201n”,
    "car_model": "1”,
    "brand": “Tata”,
    “name”: “Indica”,
    “color”: “Black”
  },
{
    "phone_id": "bh97b01”,
    "brand": “IPhone”,
    “name”: “11 Pro”,
    “color”: “Black”
  }

这似乎很棘手,我不知道如何继续。任何帮助将不胜感激。

【问题讨论】:

标签: mongodb search mongoose mongodb-query mongoose-schema


【解决方案1】:

这里有几个选项。这些使用具有不同复杂程度的基本查询和 JavaScript:


选项 #1:

查询每个集合要搜索的所有字段:

var booksFound = db.books.find( { $or [ { author: <querystring>} , { name: <querystring> } ]  } ).toArray()
var carsFound = db.cars.find( { $or [ { brand: <querystring> }, { name: <querystring> }, { color: <querystring> } ] } ).toArray()
var phonesFound = db.phones.find( { $or [ { brand: <querystring> }, { name: <querystring> }, { color: <querystring> } ] } ).toArray()

合并三个结果数组使用JavaScript的Arrays#concat方法得到结果:

var resultArray = booksFound.concat(carsFound).concat(phonesFound);


索引和排序规则: 请注意,您必须在每个集合中的各个字段上创建索引,以便更快地搜索。您还可以使用 collat​​ion 向索引添加 不区分大小写 选项(用于不区分大小写的搜索):{ collation: { locale: 'en', strength: 2 } }。请参阅Case Insensitive Indexes 上的说明。



选项 #2:

创建一个新的 keywords 字段,它将是您要搜索的字段中的值的 array。您可以将该字段命名为“关键字”或“搜索词”。

例如cars集合的文档为car_id: "nlp240n",可以将关键字字段设为keywords: [ "Hyundai", "Verna", "Blue"]

您需要在此数组字段上创建索引以便更快地查询。数组上的索引称为多键索引。您还可以使用排序规则向索引添加 不区分大小写 选项。 有关排序规则的更多详细信息,请参阅 OPTION#1

注意:需要在三个集合上创建关键字字段和索引。

进行三个查询并将每个查询的结果作为一个数组获取:

var booksFound = db.books.find( { keywords: <querystring> } ).toArray();
var carsFound = db.cars.find( { keywords: <querystring> } ).toArray();
var phonesFound = db.phones.find( { keywords: <querystring> } ).toArray();

合并三个数组使用JavaScript的Arrays#concat方法得到结果:

var resultArray = booksFound.concat(carsFound).concat(phonesFound);


如何创建关键字字段数据?

每次从集合中插入、更新或删除文档(,如果我们正在查询的任何字段),都需要相应地更新关键字数组。 插入时将值添加到数组中,更新时更改数组中的值,删除时删除数组中的值

更多信息请参见:Array Update Operators

【讨论】:

    【解决方案2】:

    在你的情况下,你可以这样做:

    var searchValue = "Martin";
    // FOR EACH COLLECTION IN MONGODB...
    // HERE YOU COULD ITERAVE OVER AN ARRAY OF COLLECTIONS NAMES...
    // var collections = ["Books", "Cars", "Phones"];
    // collections.forEach(
    db.getCollectionNames().forEach(
        function(collectionName) {
            // GETTING THE FIELD NAMES FOR THE COLLECTION...
            // FOR COLLECTIONS WITH MANY DOCUMENTS IT MAY BE MORE INTERESTING TO GET THE FIELD NAMES ELSEWHERE INSTEAD OF MONGODB...
            db.getCollection(collectionName).aggregate([
              {"$project":{"arrayOfKeyValue":{"$objectToArray":"$$ROOT"}}},
              {"$unwind":"$arrayOfKeyValue"},
              {"$group":{"_id":null,"allFields":{"$addToSet":"$arrayOfKeyValue.k"}}},
              {"$project":{"collectionName": collectionName, "fieldNames": "$allFields"}}
            ]).forEach(
                function(collectionWithFieldNames) {  
                    // FOR EACH FIELD NAME OF THE COLLECTION...
                    collectionWithFieldNames.fieldNames.forEach(
                        function(fieldName) {
                            var name = fieldName;
                            var value = searchValue;
                            var query = {};
                            query[name] = value;
    
                            // QUERY THE COLLECTION SEARCHING THE SEARCH VALUE ON THE FIELD IN THE COLLECTION...
                            db.getCollection(collectionName).find(query).forEach(
                                function(result) {
                                    // PRINT THE RESULT IF EXISTS...
                                    // HERE YOU CAN DO EVERYTHING WITH THE RESULT...
                                    print(JSON.stringify(result));
                                }
                            );
                        }
                    );
                }
            )
        }
    );
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-07-29
      • 1970-01-01
      • 2020-03-07
      • 2021-12-18
      • 1970-01-01
      • 2012-03-18
      • 2021-12-13
      • 1970-01-01
      相关资源
      最近更新 更多