키 이름의 MongoDB 도트(.)
mongo에서는 도트(.)나 달러 기호($)가 있는 키를 삽입할 수 없는 것 같습니다만, mongo Import 툴을 사용하여 도트가 들어간 JSON 파일을 Import 했을 때는 정상적으로 동작했습니다.드라이버가 그 요소를 삽입하려고 한다고 불평하고 있습니다.
데이터베이스의 문서는 다음과 같습니다.
{
"_id": {
"$oid": "..."
},
"make": "saab",
"models": {
"9.7x": [
2007,
2008,
2009,
2010
]
}
}
이 모든 것이 잘못되어 외부 데이터(모델 등)에 해시 맵을 사용하면 안 되는 건가요?아니면 어떻게든 점을 벗어날 수 있을까요?자바스크립트 같은 생각을 너무 많이 했나 봐요.
MongoDB는 도트가 있는 키를 지원하지 않기 때문에 가져오기 전에 JSON 파일을 제거/교체하기 위해 사전 처리를 해야 합니다.그렇지 않으면 모든 종류의 문제에 대처할 수 있습니다.
이 문제에 대한 표준적인 회피책은 없습니다.최선의 접근법은 상황의 세부 사항에 따라 너무 다릅니다.그러나 JSON 재구축은 아마도 일회성 비용이 될 수 있기 때문에 가능한 한 주요 인코더/디코더 접근방식은 피하고 싶습니다.
와 같이 는 MongoDB를 하지 않습니다.$
★★★★★★★★★★★★★★★★★」.
필드 이름의 제한으로 인해 문자가 맵 키로 지정됩니다.그러나 "Dollar Sign Operator Escape"에서 언급한 바와 같이, 이러한 키로 문서를 삽입할 수 없도록 하는 것은 아니며, 문서를 업데이트하거나 쿼리할 수 없도록 할 뿐입니다.
「」를 치환하는 .
[dot]
★★★★★★★★★★★★★★★★★」U+FF0E
되어 있는 와 같이) 를 저장하려고 할 때 [dot]
★★★★★★★★★★★★★★★★★」U+FF0E
Fantom의 afMorphia 드라이버가 취하는 접근법은 Java와 유사한 Unicode 이스케이프 시퀀스를 사용하되 이스케이프 문자를 먼저 이스케이프하는 것입니다.기본적으로 다음과 같은 문자열 치환이 이루어집니다(*).
\ --> \\
$ --> \u0024
. --> \u002e
이후 MongoDB에서 맵 키를 읽을 때 역치환이 이루어집니다.
또는 Fantom 코드:
Str encodeKey(Str key) {
return key.replace("\\", "\\\\").replace("\$", "\\u0024").replace(".", "\\u002e")
}
Str decodeKey(Str key) {
return key.replace("\\u002e", ".").replace("\\u0024", "\$").replace("\\\\", "\\")
}
사용자가 이러한 변환을 인식할 필요가 있는 것은 이러한 키에 대한 쿼리를 구성할 때뿐입니다.
일반적으로 은 given given given given given given given given given given given given given given given given given 。dotted.property.names
이러한 맵 키를 단순히 금지하는 것보다 이 접근법이 더 바람직하다고 생각합니다.
(*) afMorphia는 실제로 Java의 Unicode 이스케이프 구문에 기재되어 있는 완전하고 적절한 Unicode 이스케이프 규칙을 실행하지만, 기재되어 있는 치환 시퀀스는 그대로 기능합니다.
MongoDB의 최신 안정 버전(v3.6.1)은 현재 키 또는 필드 이름에 점(.)을 지원합니다.
필드 이름에는 점(.)과 달러($) 문자를 사용할 수 있습니다.
Mongo 문서는 다음과 같은 불법 문자를 대체할 것을 제안합니다.$
★★★★★★★★★★★★★★★★★」.
이치노
이러한 상황에서는 예약된 $ 및 . 문자를 키로 대체해야 합니다.어떤 문자라도 상관없습니다만, Unicode 전폭에 대응하는 문자를 사용하는 것을 검토해 주세요.U+FF04(즉, "")")와 U+FF0E(즉, "")입니다.
제가 방금 구현한 솔루션은 키 이름과 값을 두 개의 다른 필드로 나누는 것입니다.이렇게 하면 캐릭터를 그대로 유지할 수 있고 악몽을 해석하는 것에 대해 걱정할 필요가 없습니다.문서는 다음과 같습니다.
{
...
keyName: "domain.com",
keyValue: "unregistered",
...
}
할 수 find
[ keyName and keyValue ]필드에 표시됩니다.
그래서 다음 대신:
db.collection.find({"domain.com":"unregistered"})
실제로 예상대로 작동하지 않을 경우 다음과 같이 실행됩니다.
db.collection.find({keyName:"domain.com", keyValue:"unregistered"})
그러면 예상한 서류가 반환됩니다.
키에서 값 대신 해시를 사용하여 해당 값을 JSON 값에 저장할 수 있습니다.
var crypto = require("crypto");
function md5(value) {
return crypto.createHash('md5').update( String(value) ).digest('hex');
}
var data = {
"_id": {
"$oid": "..."
},
"make": "saab",
"models": {}
}
var version = "9.7x";
data.models[ md5(version) ] = {
"version": version,
"years" : [
2007,
2008,
2009,
2010
]
}
그런 다음 나중에 해시를 사용하여 모델에 액세스합니다.
var version = "9.7x";
collection.find( { _id : ...}, function(e, data ) {
var models = data.models[ md5(version) ];
}
현재 지원되고 있습니다.
MongoDb 3.6 이후에는 필드 이름에서 도트와 달러를 모두 지원합니다.아래 JIRA 참조:https://jira.mongodb.org/browse/JAVA-2810
Mongodb를 3.6 이상으로 업그레이드하는 것이 가장 좋은 방법입니다.
열쇠를 피해야 할 거야.대부분의 사람들이 제대로 줄을 피하는 방법을 모르는 것 같기 때문에, 다음과 같은 단계를 거칩니다.
- 이스케이프 문자를 선택합니다(거의 사용하지 않는 문자를 선택하는 것이 좋습니다).예: '~'
- 이스케이프하려면 먼저 이스케이프 문자의 모든 인스턴스를 이스케이프 문자 앞에 있는 시퀀스(예: '~' -> '~t')로 바꾼 다음 이스케이프 문자 앞에 있는 시퀀스 또는 이스케이프 문자를 바꿉니다.예. -> '~p'
- 이스케이프를 해제하려면 먼저 두 번째 이스케이프 시퀀스의 모든 인스턴스(예: '~p' -> '.)에서 이스케이프 시퀀스를 제거한 후 이스케이프 문자 시퀀스를 단일 이스케이프 문자(예: '~s' -> '~')로 변환합니다.
또한 mongo는 키가 $로 시작하는 것을 허용하지 않기 때문에 거기서 유사한 작업을 수행해야 합니다.
이 기능을 하는 코드는 다음과 같습니다.
// returns an escaped mongo key
exports.escape = function(key) {
return key.replace(/~/g, '~s')
.replace(/\./g, '~p')
.replace(/^\$/g, '~d')
}
// returns an unescaped mongo key
exports.unescape = function(escapedKey) {
return escapedKey.replace(/^~d/g, '$')
.replace(/~p/g, '.')
.replace(/~s/g, '~')
}
MongoDB 문서에서 ".'. 문자는 키 이름 어디에도 표시되지 않아야 합니다."부호화 방식을 생각해내든지 아니면 없애든지 해야 할 것 같아요.
이지만, 몽고를 은 봄과 몽고에서 을 관리할 수 .MappingMongoConverter
홍콩 봄
@Autowired
private MappingMongoConverter converter;
@PostConstruct
public void configureMongo() {
converter.setMapKeyDotReplacement("xxx");
}
저장된 Json의 경우:
{ "axxxb" : "value" }
봄(MongoClient)에서는 다음과 같이 읽힙니다.
{ "a.b" : "value" }
또 다른 사용자가 언급했듯이, 나중에 부호화/복호화가 문제가 될 수 있으므로 점이 있는 모든 키를 교체하는 것이 더 쉬울 수 있습니다.다음은 키를 '.'로 바꾸기 위해 만든 재귀 함수입니다.
def mongo_jsonify(dictionary):
new_dict = {}
if type(dictionary) is dict:
for k, v in dictionary.items():
new_k = k.replace('.', '-')
if type(v) is dict:
new_dict[new_k] = mongo_jsonify(v)
elif type(v) is list:
new_dict[new_k] = [mongo_jsonify(i) for i in v]
else:
new_dict[new_k] = dictionary[k]
return new_dict
else:
return dictionary
if __name__ == '__main__':
with open('path_to_json', "r") as input_file:
d = json.load(input_file)
d = mongo_jsonify(d)
pprint(d)
이 코드를 수정하여 '$'를 대체할 수도 있습니다. 이는 mongo에서 키를 사용할 수 없는 또 다른 문자이기 때문입니다.
각 오브젝트 키에 대해 JavaScript에서 다음 이스케이프를 사용합니다.
key.replace(/\\/g, '\\\\').replace(/^\$/, '\\$').replace(/\./g, '\\_')
'만'을 대신한다는 것이다.$
콘솔에서 사용하기 어려운 유니코드 문자를 사용하지 않습니다. _
특수문자 : 1개, 1개)를 대체하는 것이 .$
,.
)른하지만 전통적인 방식으로는 적절히 탈출할 수 있습니다.\
.
완벽하지는 않지만 대부분의 상황에서 사용할 수 있습니다. 금지된 문자를 다른 문자로 대체하십시오.키 안에 있기 때문에, 이 새로운 글자는 꽤 드물 것입니다.
/** This will replace \ with ⍀, ^$ with '₴' and dots with ⋅ to make the object compatible for mongoDB insert.
Caveats:
1. If you have any of ⍀, ₴ or ⋅ in your original documents, they will be converted to \$.upon decoding.
2. Recursive structures are always an issue. A cheap way to prevent a stack overflow is by limiting the number of levels. The default max level is 10.
*/
encodeMongoObj = function(o, level = 10) {
var build = {}, key, newKey, value
//if (typeof level === "undefined") level = 20 // default level if not provided
for (key in o) {
value = o[key]
if (typeof value === "object") value = (level > 0) ? encodeMongoObj(value, level - 1) : null // If this is an object, recurse if we can
newKey = key.replace(/\\/g, '⍀').replace(/^\$/, '₴').replace(/\./g, '⋅') // replace special chars prohibited in mongo keys
build[newKey] = value
}
return build
}
/** This will decode an object encoded with the above function. We assume the structure is not recursive since it should come from Mongodb */
decodeMongoObj = function(o) {
var build = {}, key, newKey, value
for (key in o) {
value = o[key]
if (typeof value === "object") value = decodeMongoObj(value) // If this is an object, recurse
newKey = key.replace(/⍀/g, '\\').replace(/^₴/, '$').replace(/⋅/g, '.') // replace special chars prohibited in mongo keys
build[newKey] = value
}
return build
}
다음은 테스트입니다.
var nastyObj = {
"sub.obj" : {"$dollar\\backslash": "$\\.end$"}
}
nastyObj["$you.must.be.kidding"] = nastyObj // make it recursive
var encoded = encodeMongoObj(nastyObj, 1)
console.log(encoded)
console.log( decodeMongoObj( encoded) )
및 결과 - 값은 변경되지 않습니다.
{
sub⋅obj: {
₴dollar⍀backslash: "$\\.end$"
},
₴you⋅must⋅be⋅kidding: {
sub⋅obj: null,
₴you⋅must⋅be⋅kidding: null
}
}
[12:02:47.691] {
"sub.obj": {
$dollar\\backslash: "$\\.end$"
},
"$you.must.be.kidding": {
"sub.obj": {},
"$you.must.be.kidding": {}
}
}
디버깅 목적이 아닌 응용 프로그램에서 사용하지 않는 것을 쿼리하는 추악한 방법이 있습니다(매립형 객체에서만 작동).
db.getCollection('mycollection').aggregate([
{$match: {mymapfield: {$type: "object" }}}, //filter objects with right field type
{$project: {mymapfield: { $objectToArray: "$mymapfield" }}}, //"unwind" map to array of {k: key, v: value} objects
{$match: {mymapfield: {k: "my.key.with.dot", v: "myvalue"}}} //query
])
PHP HTML을 사용합니다.그그입니다."."
.
다음과 같이 MongoDB에 저장됩니다.
"validations" : {
"4e25adbb1b0a55400e030000" : {
"associate" : "true"
},
"4e25adb11b0a55400e010000" : {
"associate" : "true"
}
}
PHP 코드...
$entry = array('associate' => $associate);
$data = array( '$set' => array( 'validations.' . str_replace(".", `"."`, $validation) => $entry ));
$newstatus = $collection->update($key, $data, $options);
{ 'connect.sid': 's:hyeIzKRdD9aucCc5NceYw5zhHN5vpFOp.0OUaA6' }
안으로
[ [ 'connect.sid',
's:hyeIzKRdD9aucCc5NceYw5zhHN5vpFOp.0OUaA6' ] ]
사용.
var newObj = _.pairs(oldObj);
그대로 보관하고 나중에 예쁘게 변환할 수 있습니다.
나는 이 예를 Livescript에 썼다.livescript.net 웹사이트를 사용하여 평가할 수 있습니다.
test =
field:
field1: 1
field2: 2
field3: 5
nested:
more: 1
moresdafasdf: 23423
field3: 3
get-plain = (json, parent)->
| typeof! json is \Object => json |> obj-to-pairs |> map -> get-plain it.1, [parent,it.0].filter(-> it?).join(\.)
| _ => key: parent, value: json
test |> get-plain |> flatten |> map (-> [it.key, it.value]) |> pairs-to-obj
생산될 것이다
{"field.field1":1,
"field.field2":2,
"field.field3":5,
"field.nested.more":1,
"field.nested.moresdafasdf":23423,
"field3":3}
힌트를 드리겠습니다.JSON.stringify를 사용하여 객체/어레이에 도트가 있는 키 이름을 저장하고 데이터베이스에서 데이터를 가져올 때 처리할 문자열을 JSON.parse를 사용하여 객체에 해석할 수 있습니다.
또 다른 회피책:스키마를 다음과 같이 재구성합니다.
key : {
"keyName": "a.b"
"value": [Array]
}
최신 MongoDB는 도트가 있는 키를 지원하지만 Java MongoDB 드라이버는 지원하지 않습니다.그래서 자바에서 동작시키기 위해 java-mongo-driver의 github repo에서 코드를 추출하고 그에 따라 isValid Key 기능을 변경하여 새로운 jar를 만들어 지금 사용하고 있습니다.
도트를 바꿉니다(.
) 또는 달러($
( )는, 실제의 문서에서는 사용되지 않는 다른 문자입니다.그리고 점을 복원한다..
) 또는 달러($
)을 클릭합니다.이 전략은 사용자가 읽는 데이터에 영향을 주지 않습니다.
모든 문자에서 문자를 선택할 수 있습니다.
이상한 점은 mongoj를 사용하여 직접 _id를 설정하면 점으로 된 문서를 만들 수 있지만 _id가 생성되면 문서를 만들 수 없다는 것입니다.
동작:
db.testcollection.save({"_id": "testdocument", "dot.ted.": "value"}, (err, res) => {
console.log(err, res);
});
동작하지 않음:
db.testcollection.save({"dot.ted": "value"}, (err, res) => {
console.log(err, res);
});
처음에는 도트키로 문서를 갱신하는 것도 효과가 있다고 생각했는데, 도트를 서브키라고 하는 것이군요!
mongojs가 도트(서브키)를 처리하는 것을 보고 내 키에 도트가 없는지 확인합니다.
예를 들면 @JohnnyHK에서는 데이터가 더 큰 데이터 세트로 축적되기 시작하면 더 큰 문제가 발생하므로 키에서 구두점이나 '.'을 삭제해야 한다고 언급했습니다.이는 특히 $merge와 같은 집약 연산자를 호출할 때 문제를 일으키며, 이 경우 키에 액세스하여 비교해야 오류가 발생합니다.어렵게 배웠어요.처음 하시는 분들은 반복하지 말아주세요.
이 경우 마침표가 있는 속성은 사용자가 직접 쿼리하지 않습니다.그러나 사용자가 생성할 수 있습니다.
따라서 먼저 전체 모델을 직렬화하고 문자열이 특정 필드의 모든 인스턴스를 대체합니다.기간 필드는 여러 위치에 표시될 수 있으며 데이터의 구조를 예측할 수 없습니다.
var dataJson = serialize(dataObj);
foreach(pf in periodFields)
{
var encodedPF = pf.replace(".", "ENCODE_DOT");
dataJson.replace(pf, encodedPF);
}
그리고 나중에 데이터가 평탄화된 후 인코딩된 인스턴스를 교체합니다.디코딩된 버전을 파일에 쓸 수 있도록 PF를 사용합니다.
아무도 ENCODE_DOT라는 필드를 필요로 하지 않기 때문에 이 경우 문제가 되지 않습니다.
결과는 다음과 같습니다.하나는 colorENCODE_DOTONE으로 데이터베이스에 저장됩니다.
파일을 쓸 때는 ENCODE_DOT를 로 바꿉니다.
/home/user/anaconda3/lib/python3.6/site-packages/pymongo/collection.py
에러 메세지에 기재되어 있습니다.「 」를 사용하고 anaconda
수 없는 만 하면 .check_keys = True
로로 합니다.False
상기의 파일에 기재되어 있습니다.잘될!!
언급URL : https://stackoverflow.com/questions/12397118/mongodb-dot-in-key-name
'programing' 카테고리의 다른 글
JavaScript 객체가 JSON인지 확인하는 방법 (0) | 2023.03.02 |
---|---|
React Native 프로젝트에는 index.ios.js 또는 index.android가 없습니다.js (0) | 2023.03.02 |
각도 종속성에 대한 Google CDN? (0) | 2023.03.02 |
TypeScript 자동 Import의 WebStorm/PhpStorm 큰따옴표 (0) | 2023.02.25 |
on클릭청취자가 함수가 되어야 하는데 대신 유형 개체 - react redux를 얻습니다. (0) | 2023.02.25 |