搜索 MongoDB 中任何字段的值而不显式命名它
我浏览了 MongoDB 文档并用 google 搜索了这个问题,但找不到合适的答案。所以,这就是我要找的。 假设我有一个包含如下元素的集合:
{
"foo" : "bar",
"test" : "test",
"key" : "value",
}
我想要实现的是通过在所有(可能除了有限多个 ;-) )字段中搜索来查找元素。换句话说:给定一个查询,我不知道应该在哪个字段中找到该查询。
在我看来,这样的东西
db.things.find({_ANY_ : "bar"})
会给我示例元素。
感谢您的帮助。
I looked through the MongoDB documentation and googled this question but couldn't really find a suitable answer. So, here is what I'm looking for.
Assume I have a collection with elements like this:
{
"foo" : "bar",
"test" : "test",
"key" : "value",
}
What I'd like to achieve is find an element by searching in all (maybe except for finitely many ;-) ) fields. In other words: Given a query, I do NOT know in which field the query should be found.
In my thinking something like this
db.things.find({_ANY_ : "bar"})
would give me the example element.
Thank you for your help.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
要对所有字段进行文本搜索,您首先必须在所有字段上创建文本索引。
正如 mongodb 文档 所示,“允许在所有包含字符串内容的字段,使用通配符说明符($**)来索引所有包含字符串内容的字段。”
如果您在 mongo shell 中工作(通过调用“mongo”从命令行执行),那么您可以使用此命令来执行此操作,其中“collection”是您要使用的数据库中集合的名称。
db.collection.createIndex({ "$**": "text" },{ name: "TextIndex" })
第二个对象,即
{name:"TextIndex"}, 是可选的...您实际上不需要为索引指定名称,因为每个集合只能有一个文本索引(一次...如果需要,您可以删除索引并创建新索引)。
在所有字段上创建文本索引后,您可以使用以下查询对象进行简单的文本搜索:
{ $text : { $search: <您的字符串>;因此
,如果您正在编写 JavaScript 函数,您可能会执行以下操作:
varcursor = db.collection().find({ $text: { $search:} });
有关控制搜索的各种方法的更多信息,请参阅有关文本搜索的 mongodb 文档 此处
to do a text search on all fields, you first must create a text index on all fields.
as the mongodb documentation indicates, "To allow for text search on all fields with string content, use the wildcard specifier ($**) to index all fields that contain string content."
if you are working inside the mongo shell (which you execute from the command line by calling 'mongo'), then you can do it with this command, where 'collection' is the name of the collection in the db you want to use.
db.collection.createIndex({ "$**": "text" },{ name: "TextIndex" })
the second object, i.e.
{name:"TextIndex"}
, is optional...you don't actually need to give the index a name, since there can only be a single text index per collection (at a time...you can drop indexes and create new ones if you want).once you have created a text index on all fields, you can do a simple text search with the following query object:
{ $text : { $search: <your string> } }
so, if you are writing a javascript function you might do something like:
var cursor = db.collection(<collection_name>).find({ $text: { $search: <your string> } });
for more info on the various ways to control the search, see the mongodb documentation on text searching here
这个类似问题的答案有您的解决方案,为了完整起见,我将在此处重复该解决方案。您可以使用
$where
< /a> 运算符在 MongoDB 服务器上运行任意 JavaScript,但需要注意的是,这将比几乎任何其他类型的查询慢得多。对于您的示例,它将是:This answer to a similar question has your solution, which I'll repeat here for completeness. You can use the
$where
operator to run arbitrary JavaScript on the MongoDB server(s), with the caveat that this will be much slower than almost any other kind of query. For your example, it would be:如果不单独检查应用程序端文档或通过服务器端代码执行,这是不可能的。考虑将您的架构更改为:
这显然有一些缺点(主要是性能和污染架构),但将允许您通过以下方式实现所需的功能:
This is not possible without individually inspecting documents app-side or through server-side code execution. Consider changing your schema to :
This obviously has some downsides (performance and poluted schema mostly) but will allow what you need through :
遗憾的是,前面的答案都没有解决 mongo 可以在数组或嵌套对象中包含嵌套值的事实。
这是正确的查询:
由于在数组或嵌套对象上调用 typeof 将返回“object”,这意味着查询将迭代所有嵌套元素,并将迭代所有元素,直到找到具有值的键。
您可以使用嵌套值检查以前的答案,结果将远远达不到预期。
字符串化整个对象的性能要低得多,因为它必须一一迭代所有内存扇区以尝试匹配它们。并在 RAM 内存中以字符串形式创建对象的副本(由于查询使用更多 RAM,效率低下,并且由于函数上下文已经加载了对象,因此速度较慢)
Sadly, none of the previous answers address the fact that mongo can contain nested values in arrays or nested objects.
THIS IS THE CORRECT QUERY:
Since calling typeof on array or nested object will return 'object' this means that the query will iterate on all nested elements and will iterate through all of then until the key with value will be found.
You can check previous answers with a nested value and the results will be far from desired.
Stringifying the whole object is far less performant since it has to iterate through all memory sectors one by one trying to match them. And creates a copy of the object as a string in ram memory (both inefficient since query uses more ram and slow since function context already has a loaded object)
使用 $where 与进行全表扫描相同,不能使用索引。我也无法让它工作,但是我确实发现它有效(它也相当于全表扫描):
其中
/needle/
是在文档[键]
Using $where is the same as doing a full table scan and cannot use the indexes. I also could not get it working, however I did find this worked (it also does the equivalent of a full table scan) :
where
/needle/
is a regular expression to find in the value ofdoc[key]
您可以使用递归函数来完成此操作:
You can do it with a recursive function:
要进行文本搜索,您必须为集合创建文本索引。
有关更多信息,请查看 mongo 文档:索引文本
To do text search, you have to create text indexes for your collection.
For more information, look at mongo documentation :indexes text
对 MongoDB 的快速而肮脏的整个数据库搜索是将数据库导出为 JSON 并通过导出导出到
grep
:当然,您的搜索词将在键名称和值上匹配,但有时这甚至很方便(例如,开发人员试图在大型文档中的文档结构更改后查找字段)。
对于大型数据库,该解决方案效率非常低,但在仅存在测试数据的开发过程中,它非常方便。
MongoDB 导出到 JSON 的更多详细信息和解释的来源是 Tom Boutell 对“如何导出 MongoDB 中的所有集合?”的回答。
A quick-and-dirty whole-database search for MongoDB is to export the database to JSON and to
grep
through the export:Of course then your search term will match on both key names and values, but sometimes that is even handy (e.g. developer trying to find a field after document structure changes in a large document).
This solution will be very inefficient for massive databases, but it's handy during development when only test data is present.
The source, with more details and explanations, for the MongoDB export to JSON is Tom Boutell's answer for "How to export all collections in MongoDB?".