Firestore 查询 endBefore 和 endAt 未按预期工作
Firestore query endBefore & endAt not working as expected
我正在使用 Node 10、firebase 8.0、firebase-admin 9.3.0。我已经包含了我的测试代码和客户端 js 版本的副本。
数据
Document ID | name | is_visible
----------- | ---- | ----------
1 | a | true
2 | b | true
3 | c | true
4 | d | true
5 | e | true
6 | f | true
7 | g | true
8 | h | true
9 | i | true
代码
var admin = require("firebase-admin");
const firebaseConfig = {xxx}
admin.initializeApp({
credential: admin.credential.cert(firebaseConfig)
});
const getDocs = async () =>{
try {
const cursor = await admin.firestore().collection('ordering').doc('5').get();
const beforeDocs = await admin.firestore().collection('ordering')
.orderBy("name", "desc")
.endAt(cursor)
.limit(2)
.get()
beforeDocs.forEach((doc)=> {
console.log("Doc ID - ",doc.id, ", Name -", doc.get('name'));
})
const afterDocs = await admin.firestore().collection('ordering')
.orderBy("name", "desc")
.startAt(cursor)
.limit(2)
.get()
afterDocs.forEach((doc)=> {
console.log("Doc ID - ",doc.id, ", Name -", doc.get('name'));
})
}
catch (error) {
console.error(error);
}
}
getDocs();
运行 使用 node getDocs.js
期待结果
Doc ID - 6 , Name - f
Doc ID - 5 , Name - e
Doc ID - 5 , Name - e
Doc ID - 4 , Name - d
实际结果
Doc ID - 9 , Name - i
Doc ID - 8 , Name - h
Doc ID - 5 , Name - e
Doc ID - 4 , Name - d
我对 endAt 的临时解决方法是使用 startAt 将顺序反转为“asc”,然后在 QuerySnapshot 中反转 forEach 之前的 docs 数组。
我创建了这个 JS 来显示我的问题,这是我测试集的 运行ning,它非常粗糙,请善待,输出到控制台。
我显然做错了什么,但不确定是什么。
<script src="https://www.gstatic.com/firebasejs/8.0.0/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.0.0/firebase-firestore.js"></script>
<body>
<div id="output">Check the console!</div>
</body>
<script>
var firebaseConfig = {
apiKey: "AIzaSyAxLEo7LfABdATToJTMQGae3Vgum_CAlQg",
authDomain: "bmtestbase.firebaseapp.com",
databaseURL: "https://bmtestbase.firebaseio.com",
projectId: "bmtestbase",
storageBucket: "bmtestbase.appspot.com",
messagingSenderId: "326028950684",
appId: "1:326028950684:web:74b55887466c63b4a9c159"
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
const db = firebase.firestore()
// Setting the Focus point using a Snapshot
db.collection('ordering').get()
.then (docs => {
docs.forEach(doc => {
console.log("MYCODE_allDocs: DocID ", doc.id, ", Name ", doc.get('name'))
})
})
db.collection('ordering').doc('5').get()
.then( focusSnapshot => {
db.collection("ordering")
.orderBy("name", "asc")
.endAt(focusSnapshot)
.limit(2)
.get()
.then(docs => {
console.log("MYCODE_endAt_expected:","DocID 4, Name d")
console.log("MYCODE_endAt_expected:","DocID 5, Name e")
docs.forEach(doc => {
console.log("MYCODE_endAt:","DocID ", doc.id, ", Name ", doc.get('name'))
});
})
db.collection("ordering")
.orderBy("name", "asc")
.startAt(focusSnapshot)
.limit(2)
.get()
.then(docs => {
console.log("MYCODE_startAt_expected:","DocID 5, Name e")
console.log("MYCODE_startAt_expected:","DocID 6, Name f")
docs.forEach(doc => {
console.log("MYCODE_startAt:","DocID ", doc.id, ", Name ", doc.get('name'))
});
})
})
</script>
我认为您对 startAt 和 endAt 的期望不正确。我建议查看 documentation.
关于startAt,它说:
Use the startAt() or startAfter() methods to define the start point for a query. The startAt() method includes the start point, while the startAfter() method excludes it.
因此,如果您传递限制为 5 的 startAt()
的快照,您将从该文档开始查询,并获得查询顺序中紧随其后的 4 个文档。
Similarly, use the endAt() or endBefore() methods to define an end point for your query results.
endAt()
限制为 5 会导致查询结果在该文档处停止。因此,除了查询顺序中位于它之前的 4 个文档之外,您还将获得该文档。
根据 firebase 支持,您需要使用 limitToLast with endBefore and endAt
像这样重写您的示例应该可行:
<script src="https://www.gstatic.com/firebasejs/8.0.0/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.0.0/firebase-firestore.js"></script>
<body>
<div id="output">Check the console!</div>
</body>
<script>
var firebaseConfig = {
apiKey: "AIzaSyAxLEo7LfABdATToJTMQGae3Vgum_CAlQg",
authDomain: "bmtestbase.firebaseapp.com",
databaseURL: "https://bmtestbase.firebaseio.com",
projectId: "bmtestbase",
storageBucket: "bmtestbase.appspot.com",
messagingSenderId: "326028950684",
appId: "1:326028950684:web:74b55887466c63b4a9c159"
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
const db = firebase.firestore()
// Setting the Focus point using a Snapshot
db.collection('ordering').get()
.then (docs => {
docs.forEach(doc => {
console.log("MYCODE_allDocs: DocID ", doc.id, ", Name ", doc.get('name'))
})
})
db.collection('ordering').doc('5').get()
.then( focusSnapshot => {
db.collection("ordering")
.orderBy("name", "asc")
.endAt(focusSnapshot)
.limitToLast(2)
.get()
.then(docs => {
console.log("MYCODE_endAt_expected:","DocID 4, Name d")
console.log("MYCODE_endAt_expected:","DocID 5, Name e")
docs.forEach(doc => {
console.log("MYCODE_endAt:","DocID ", doc.id, ", Name ", doc.get('name'))
});
})
db.collection("ordering")
.orderBy("name", "asc")
.startAt(focusSnapshot)
.limit(2)
.get()
.then(docs => {
console.log("MYCODE_startAt_expected:","DocID 5, Name e")
console.log("MYCODE_startAt_expected:","DocID 6, Name f")
docs.forEach(doc => {
console.log("MYCODE_startAt:","DocID ", doc.id, ", Name ", doc.get('name'))
});
})
})
</script>
我正在使用 Node 10、firebase 8.0、firebase-admin 9.3.0。我已经包含了我的测试代码和客户端 js 版本的副本。
数据
Document ID | name | is_visible
----------- | ---- | ----------
1 | a | true
2 | b | true
3 | c | true
4 | d | true
5 | e | true
6 | f | true
7 | g | true
8 | h | true
9 | i | true
代码
var admin = require("firebase-admin");
const firebaseConfig = {xxx}
admin.initializeApp({
credential: admin.credential.cert(firebaseConfig)
});
const getDocs = async () =>{
try {
const cursor = await admin.firestore().collection('ordering').doc('5').get();
const beforeDocs = await admin.firestore().collection('ordering')
.orderBy("name", "desc")
.endAt(cursor)
.limit(2)
.get()
beforeDocs.forEach((doc)=> {
console.log("Doc ID - ",doc.id, ", Name -", doc.get('name'));
})
const afterDocs = await admin.firestore().collection('ordering')
.orderBy("name", "desc")
.startAt(cursor)
.limit(2)
.get()
afterDocs.forEach((doc)=> {
console.log("Doc ID - ",doc.id, ", Name -", doc.get('name'));
})
}
catch (error) {
console.error(error);
}
}
getDocs();
运行 使用 node getDocs.js
期待结果
Doc ID - 6 , Name - f
Doc ID - 5 , Name - e
Doc ID - 5 , Name - e
Doc ID - 4 , Name - d
实际结果
Doc ID - 9 , Name - i
Doc ID - 8 , Name - h
Doc ID - 5 , Name - e
Doc ID - 4 , Name - d
我对 endAt 的临时解决方法是使用 startAt 将顺序反转为“asc”,然后在 QuerySnapshot 中反转 forEach 之前的 docs 数组。
我创建了这个 JS 来显示我的问题,这是我测试集的 运行ning,它非常粗糙,请善待,输出到控制台。
我显然做错了什么,但不确定是什么。
<script src="https://www.gstatic.com/firebasejs/8.0.0/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.0.0/firebase-firestore.js"></script>
<body>
<div id="output">Check the console!</div>
</body>
<script>
var firebaseConfig = {
apiKey: "AIzaSyAxLEo7LfABdATToJTMQGae3Vgum_CAlQg",
authDomain: "bmtestbase.firebaseapp.com",
databaseURL: "https://bmtestbase.firebaseio.com",
projectId: "bmtestbase",
storageBucket: "bmtestbase.appspot.com",
messagingSenderId: "326028950684",
appId: "1:326028950684:web:74b55887466c63b4a9c159"
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
const db = firebase.firestore()
// Setting the Focus point using a Snapshot
db.collection('ordering').get()
.then (docs => {
docs.forEach(doc => {
console.log("MYCODE_allDocs: DocID ", doc.id, ", Name ", doc.get('name'))
})
})
db.collection('ordering').doc('5').get()
.then( focusSnapshot => {
db.collection("ordering")
.orderBy("name", "asc")
.endAt(focusSnapshot)
.limit(2)
.get()
.then(docs => {
console.log("MYCODE_endAt_expected:","DocID 4, Name d")
console.log("MYCODE_endAt_expected:","DocID 5, Name e")
docs.forEach(doc => {
console.log("MYCODE_endAt:","DocID ", doc.id, ", Name ", doc.get('name'))
});
})
db.collection("ordering")
.orderBy("name", "asc")
.startAt(focusSnapshot)
.limit(2)
.get()
.then(docs => {
console.log("MYCODE_startAt_expected:","DocID 5, Name e")
console.log("MYCODE_startAt_expected:","DocID 6, Name f")
docs.forEach(doc => {
console.log("MYCODE_startAt:","DocID ", doc.id, ", Name ", doc.get('name'))
});
})
})
</script>
我认为您对 startAt 和 endAt 的期望不正确。我建议查看 documentation.
关于startAt,它说:
Use the startAt() or startAfter() methods to define the start point for a query. The startAt() method includes the start point, while the startAfter() method excludes it.
因此,如果您传递限制为 5 的 startAt()
的快照,您将从该文档开始查询,并获得查询顺序中紧随其后的 4 个文档。
Similarly, use the endAt() or endBefore() methods to define an end point for your query results.
endAt()
限制为 5 会导致查询结果在该文档处停止。因此,除了查询顺序中位于它之前的 4 个文档之外,您还将获得该文档。
根据 firebase 支持,您需要使用 limitToLast with endBefore and endAt
像这样重写您的示例应该可行:
<script src="https://www.gstatic.com/firebasejs/8.0.0/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.0.0/firebase-firestore.js"></script>
<body>
<div id="output">Check the console!</div>
</body>
<script>
var firebaseConfig = {
apiKey: "AIzaSyAxLEo7LfABdATToJTMQGae3Vgum_CAlQg",
authDomain: "bmtestbase.firebaseapp.com",
databaseURL: "https://bmtestbase.firebaseio.com",
projectId: "bmtestbase",
storageBucket: "bmtestbase.appspot.com",
messagingSenderId: "326028950684",
appId: "1:326028950684:web:74b55887466c63b4a9c159"
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
const db = firebase.firestore()
// Setting the Focus point using a Snapshot
db.collection('ordering').get()
.then (docs => {
docs.forEach(doc => {
console.log("MYCODE_allDocs: DocID ", doc.id, ", Name ", doc.get('name'))
})
})
db.collection('ordering').doc('5').get()
.then( focusSnapshot => {
db.collection("ordering")
.orderBy("name", "asc")
.endAt(focusSnapshot)
.limitToLast(2)
.get()
.then(docs => {
console.log("MYCODE_endAt_expected:","DocID 4, Name d")
console.log("MYCODE_endAt_expected:","DocID 5, Name e")
docs.forEach(doc => {
console.log("MYCODE_endAt:","DocID ", doc.id, ", Name ", doc.get('name'))
});
})
db.collection("ordering")
.orderBy("name", "asc")
.startAt(focusSnapshot)
.limit(2)
.get()
.then(docs => {
console.log("MYCODE_startAt_expected:","DocID 5, Name e")
console.log("MYCODE_startAt_expected:","DocID 6, Name f")
docs.forEach(doc => {
console.log("MYCODE_startAt:","DocID ", doc.id, ", Name ", doc.get('name'))
});
})
})
</script>