MongoDB:如何索引未知字段

时间:2018-09-26 08:21:37

标签: mongodb mongodb-query mongodb-indexes

我们正在存储结构未定义的文档。我的意思是,它具有基本结构(public static bool ContainsDuplicates<T>(this IEnumerable<T> items, IEnumerable<T> itemsToExclude = null) { if (itemsToExclude == null) itemsToExclude = Enumerable.Empty<T>(); HashSet<T> set = new HashSet<T>(); return !items.Except(itemsToExclude).All(set.Add); } iduser),但也有一个creationTimestamp字段,我们可以在其中存储任何结构:< / p>

Map<String, Object> values

示例:

public class Metadata {
    private String id;
    private String user;
    private Date creationTimestamp;
    private Map<String, Object> values;
}

因此,您可以看到> db.metadata.find(); { "_id" : "Doc2Ref2Mdt1", "user" : "user1", "creationTimestamp" : ISODate("2018-09-24T12:20:56.958Z"), "values" : { "ambit" : "ctti", "departament" : "economia" } }, { "_id" : "Doc1Ref2Mdt1", "user" : "user2", "creationTimestamp" : ISODate("2018-09-24T12:20:56.169Z"), "values" : { "date" : ISODate("2018-09-24T12:20:56.171Z"), "number" : 16, "address" : { "street" : "Av. Diagonal", "location" : "barcelona", "credentials" : [ { "password" : "pwd", "login" : "main" }, { "password" : "pwd", "login" : "other", "creation" : ISODate("2018-09-24T12:20:56.171Z") }], "contact" : "contact name", "tags" : ["tag1", "tag2"}] } } 可以存储任何结构。

我需要知道mongodb是否能够自动为所有索引。

我的意思是,例如,当将新字段“添加”到values中时,values会自动被索引。

有什么想法吗?

3 个答案:

答案 0 :(得分:2)

从4.2版开始,MongoDB现在支持所谓的通配符索引

假设您收集的对象具有以下结构

{ "userMetadata" : { "likes" : [ "dogs", "cats" ] } }
{ "userMetadata" : { "dislikes" : "pickles" } }
{ "userMetadata" : { "age" : 45 } }
{ "userMetadata" : "inactive" }

您可以添加此索引:

db.userData.createIndex( { "userMetadata.$**" : 1 } )

此索引将支持以下查询:

db.userData.find({ "userMetadata.likes" : "dogs" })
db.userData.find({ "userMetadata.dislikes" : "pickles" })
db.userData.find({ "userMetadata.age" : { $gt : 30 } })
db.userData.find({ "userMetadata" : "inactive" })

您也可以查看文档。 https://docs.mongodb.com/manual/core/index-wildcard/

答案 1 :(得分:0)

您可以在子文档上创建索引,并且新字段将自动添加,

但是

要在查询中使用此索引,必须提供完整且有序文档作为参数。

示例,以及您的示例:

db.metadata.createIndex({"values",1});

  

db.metadata.find(“ values.ambit”:“ ctti”)

==>将不使用索引,但将返回第一个文档。

  

db.metadata.find(values:{ambit:“ ctti”})

==>将使用索引,但不返回任何文档。

  

db.metadata.find(values:{“ departament”:“ economia”,ambit:“ ctti”})

==>由于字段顺序不同,将使用索引,但不返回任何文档。

  

db.metadata.find(values:{ambit:“ ctti”,“ departament”:“ economia”})

==>将使用索引,并返回返回第一个文档。

答案 2 :(得分:0)

不可能以您想要的方式。

您可以先尝试text index on all fields,然后再进行实际查询。单独的文本搜索可能会导致假阳性匹配,但与常规查询聚合会减少要扫描的数据集,并且在大多数情况下会加快搜索速度。

要牢记一些限制:

  • 仅索引字符串字段,例如.find({ $text: { $search: "2018-09-24" } })将不会返回任何内容。 .find({ $text: { $search: "16" } })
  • 都不会
  • 仅全字查询,即无正则表达式。您将需要使用language: "none"来保留停用词,并且不要使用词干。诸如.find({ $text: { $search: "barcel" } })之类的查询找不到第二个文档。

如果您控制所有写入,则可以通过将values映射序列化为写入时的字符串字段来解决第一个限制。然后,您将仅需要在此字段上创建文本索引。