There is a solution for the dot number of. In the mongo data set property

  • 2020-12-09 01:07:10
  • OfStack

preface

MongoDB is a document-oriented database for collection storage. The basic concepts involved in MongoDB are different from relational databases. This article is mainly about the mongo data set attributes exist the dot (.) related content, the following is not enough, let's start with the detailed introduction

Basic Knowledge:

1. It seems that mongo3.6 did not allow inserting keys with dots (.) or dollar signs ($) before, but when I used the mongoimport tool to import JSON files with dots, it worked fine.

2. When using ES14en-ES15en-ES16en to process mongodb's add, delete, change and check, one MappingMongoConverter(Document and Modle conversion classes) will be used to convert the data

3. The specific conversion of the dot number is DBObjectAccessor(ES24en-ES25en-ES26en-1.10.13) or DocumentAccessor(ES28en-ES29en-ES30en-2.0.9), as follows:


// Insert-time conversion 
public void put(MongoPersistentProperty prop, Object value) {
 Assert.notNull(prop, "MongoPersistentProperty must not be null!");
 String fieldName = prop.getFieldName();
 if (!fieldName.contains(".")) {
  dbObject.put(fieldName, value);
  return;
 }
 Iterator<String> parts = Arrays.asList(fieldName.split("\\.")).iterator();
 DBObject dbObject = this.dbObject;
 while (parts.hasNext()) {
  String part = parts.next();
  if (parts.hasNext()) {
   dbObject = getOrCreateNestedDbObject(part, dbObject);
  } else {
   dbObject.put(part, value);
  }
 }
}

// Query time conversion 
public Object get(MongoPersistentProperty property) {
 String fieldName = property.getFieldName();
 if (!fieldName.contains(".")) {
  return this.dbObject.get(fieldName);
 }
 Iterator<String> parts = Arrays.asList(fieldName.split("\\.")).iterator();
 Map<String, Object> source = this.dbObject;
 Object result = null;
 while (source != null && parts.hasNext()) {
  result = source.get(parts.next());
  if (parts.hasNext()) {
   source = getAsMap(result);
  }
 }
 return result;
}

// Determine if the value is null 
public boolean hasValue(MongoPersistentProperty property) {
 Assert.notNull(property, "Property must not be null!");
 String fieldName = property.getFieldName();
 if (!fieldName.contains(".")) {
  return this.dbObject.containsField(fieldName);
 }
 String[] parts = fieldName.split("\\.");
 Map<String, Object> source = this.dbObject;
 Object result = null;
 for (int i = 1; i < parts.length; i++) {
  result = source.get(parts[i - 1]);
  source = getAsMap(result);
  if (source == null) {
   return false;
  }
 }
 return source.containsKey(parts[parts.length - 1]);
}

4. The dot has the meaning of subset in mongodb

For example, query A.B attribute: query is the value of B attribute in the collection corresponding to the subcollection of A, not the attribute of ES41en.B in the query collection

Problem description: What the document looks like in the database:


{
 "_id": ObjectId("5bae00765500af6307755111"),
 "name": "java",
 "age": 26,
 "A.B": "nnnn"
}

Therefore, using @Field (" A.B ") in Model does not retrieve the value of "A.B" in the collection


@Field("A.B")
@JSONField(serialzeFeatures = SerializerFeature.DisableCircularReferenceDetect)
private Integer ab;  

5. Solutions:

After consulting various materials, I have the following experience: the dot can be inserted in MongoDB, which should start from version 3.6. Although the official document says that the dot can be supported, the third party driver, spring-ES62en-ES63en does not support it. However, since spring-ES65en-ES66en has been used in the project from the beginning of 1, it is difficult to replace it, so I want to cover the conversion method.

How do I overwrite a file in the ES69en-ES70en-mongodb package?

Create a new directory similar to the DBObjectAccessor conversion file 1, rebuild the DBObjectAccessor class copy code custom modifications, after compilation or use the new class first.


// Query time conversion 
public Object get(MongoPersistentProperty property) {
 String fieldName = property.getFieldName();
 return this.dbObject.get(fieldName);
}
 
// Determine if the value is null 
public boolean hasValue(MongoPersistentProperty property) {
 Assert.notNull(property, "Property must not be null!");
 String fieldName = property.getFieldName();
 return this.dbObject.containsField(fieldName);
}

Note: Do not modify the put method as much as possible, because the lower version of MongoDB does not support the dot, the insertion will report an error

Of course, it's best not to have a dot in an attribute.

conclusion


Related articles: